Snapshot cdeccf6fdd8c2d494ea2867cb37a025bf8879baf
Change-Id: Ia2de32ccb97a9641462c72363b0a8c4288f4f36d
diff --git a/bta/Android.mk b/bta/Android.mk
new file mode 100644
index 0000000..7d1c19e
--- /dev/null
+++ b/bta/Android.mk
@@ -0,0 +1,104 @@
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+ifeq ($(BOARD_HAVE_BLUETOOTH_BCM),true)
+LOCAL_CFLAGS += \
+ -DBOARD_HAVE_BLUETOOTH_BCM
+endif
+LOCAL_CFLAGS += -DBUILDCFG $(bdroid_CFLAGS)
+
+LOCAL_PRELINK_MODULE:=false
+LOCAL_SRC_FILES:= \
+ ./dm/bta_dm_ci.c \
+ ./dm/bta_dm_act.c \
+ ./dm/bta_dm_pm.c \
+ ./dm/bta_dm_main.c \
+ ./dm/bta_dm_cfg.c \
+ ./dm/bta_dm_api.c \
+ ./dm/bta_dm_sco.c \
+ ./gatt/bta_gattc_api.c \
+ ./gatt/bta_gatts_act.c \
+ ./gatt/bta_gatts_main.c \
+ ./gatt/bta_gattc_utils.c \
+ ./gatt/bta_gattc_ci.c \
+ ./gatt/bta_gatts_api.c \
+ ./gatt/bta_gattc_main.c \
+ ./gatt/bta_gattc_act.c \
+ ./gatt/bta_gattc_cache.c \
+ ./gatt/bta_gatts_utils.c \
+ ./ag/bta_ag_sdp.c \
+ ./ag/bta_ag_sco.c \
+ ./ag/bta_ag_cfg.c \
+ ./ag/bta_ag_main.c \
+ ./ag/bta_ag_api.c \
+ ./ag/bta_ag_rfc.c \
+ ./ag/bta_ag_act.c \
+ ./ag/bta_ag_cmd.c \
+ ./ag/bta_ag_ci.c \
+ ./ag/bta_ag_at.c \
+ ./hh/bta_hh_cfg.c \
+ ./hh/bta_hh_act.c \
+ ./hh/bta_hh_api.c \
+ ./hh/bta_hh_utils.c \
+ ./hh/bta_hh_main.c \
+ ./pb/bta_pbs_cfg.c \
+ ./fs/bta_fs_ci.c \
+ ./fs/bta_fs_cfg.c \
+ ./pan/bta_pan_main.c \
+ ./pan/bta_pan_ci.c \
+ ./pan/bta_pan_act.c \
+ ./pan/bta_pan_api.c \
+ ./av/bta_av_act.c \
+ ./av/bta_av_ci.c \
+ ./av/bta_av_api.c \
+ ./av/bta_av_aact.c \
+ ./av/bta_av_main.c \
+ ./av/bta_av_cfg.c \
+ ./av/bta_av_ssm.c \
+ ./av/bta_av_sbc.c \
+ ./ar/bta_ar.c \
+ ./hl/bta_hl_act.c \
+ ./hl/bta_hl_api.c \
+ ./hl/bta_hl_main.c \
+ ./hl/bta_hl_utils.c \
+ ./hl/bta_hl_sdp.c \
+ ./hl/bta_hl_ci.c \
+ ./sys/bta_sys_main.c \
+ ./sys/bta_sys_ci.c \
+ ./sys/bta_sys_conn.c \
+ ./sys/bta_sys_cfg.c \
+ ./sys/ptim.c \
+ ./sys/bd.c \
+ ./sys/utl.c \
+ ./jv/bta_jv_act.c \
+ ./jv/bta_jv_cfg.c \
+ ./jv/bta_jv_main.c \
+ ./jv/bta_jv_api.c
+
+LOCAL_MODULE := libbt-brcm_bta
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := libcutils libc
+
+LOCAL_C_INCLUDES+= . \
+ $(LOCAL_PATH)/include \
+ $(LOCAL_PATH)/sys \
+ $(LOCAL_PATH)/dm \
+ $(LOCAL_PATH)/../gki/common \
+ $(LOCAL_PATH)/../gki/ulinux \
+ $(LOCAL_PATH)/../include \
+ $(LOCAL_PATH)/../stack/include \
+ $(LOCAL_PATH)/../stack/btm \
+ $(LOCAL_PATH)/../hcis \
+ $(LOCAL_PATH)/../hcis/patchram \
+ $(LOCAL_PATH)/../udrv/include \
+ $(LOCAL_PATH)/../brcm/include \
+ $(bdroid_C_INCLUDES) \
+
+
+include $(BUILD_STATIC_LIBRARY)
+
+endif # TARGET_SIMULATOR != true
diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c
new file mode 100644
index 0000000..5f72444
--- /dev/null
+++ b/bta/ag/bta_ag_act.c
@@ -0,0 +1,867 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains action functions for the audio gateway.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_co.h"
+#include "bta_ag_int.h"
+#include "port_api.h"
+#include "utl.h"
+#include <string.h>
+#include "bta_dm_int.h"
+#include "l2c_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/* maximum length of data to read from RFCOMM */
+#define BTA_AG_RFC_READ_MAX 512
+
+/* maximum AT command length */
+#define BTA_AG_CMD_MAX 512
+
+const UINT16 bta_ag_uuid[BTA_AG_NUM_IDX] =
+{
+ UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
+ UUID_SERVCLASS_AG_HANDSFREE
+};
+
+const UINT8 bta_ag_sec_id[BTA_AG_NUM_IDX] =
+{
+ BTM_SEC_SERVICE_HEADSET_AG,
+ BTM_SEC_SERVICE_AG_HANDSFREE
+};
+
+const tBTA_SERVICE_ID bta_ag_svc_id[BTA_AG_NUM_IDX] =
+{
+ BTA_HSP_SERVICE_ID,
+ BTA_HFP_SERVICE_ID
+};
+
+const tBTA_SERVICE_MASK bta_ag_svc_mask[BTA_AG_NUM_IDX] =
+{
+ BTA_HSP_SERVICE_MASK,
+ BTA_HFP_SERVICE_MASK
+};
+
+typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+ char *p_arg, INT16 int_arg);
+
+const tBTA_AG_ATCMD_CBACK bta_ag_at_cback_tbl[BTA_AG_NUM_IDX] =
+{
+ bta_ag_at_hsp_cback,
+ bta_ag_at_hfp_cback
+};
+
+/*******************************************************************************
+**
+** Function bta_ag_cback_open
+**
+** Description Send open callback event to application.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_cback_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data, tBTA_AG_STATUS status)
+{
+ tBTA_AG_OPEN open;
+
+ /* call app callback with open event */
+ open.hdr.handle = bta_ag_scb_to_idx(p_scb);
+ open.hdr.app_id = p_scb->app_id;
+ open.status = status;
+ open.service_id = bta_ag_svc_id[p_scb->conn_service];
+ if(p_data)
+ {
+ /* if p_data is provided then we need to pick the bd address from the open api structure */
+ bdcpy(open.bd_addr, p_data->api_open.bd_addr);
+ }
+ else
+ {
+ bdcpy(open.bd_addr, p_scb->peer_addr);
+ }
+
+ (*bta_ag_cb.p_cback)(BTA_AG_OPEN_EVT, (tBTA_AG *) &open);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_register
+**
+** Description This function initializes values of the AG cb and sets up
+** the SDP record for the services.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_register(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ tBTA_AG_REGISTER reg;
+
+ /* initialize control block */
+ p_scb->reg_services = p_data->api_register.services;
+ p_scb->serv_sec_mask = p_data->api_register.sec_mask;
+ p_scb->features = p_data->api_register.features;
+ p_scb->app_id = p_data->api_register.app_id;
+
+ /* create SDP records */
+ bta_ag_create_records(p_scb, p_data);
+
+ /* start RFCOMM servers */
+ bta_ag_start_servers(p_scb, p_scb->reg_services);
+
+ /* call app callback with register event */
+ reg.hdr.handle = bta_ag_scb_to_idx(p_scb);
+ reg.hdr.app_id = p_scb->app_id;
+ reg.status = BTA_AG_SUCCESS;
+ (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG *) ®);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_deregister
+**
+** Description This function removes the sdp records, closes the RFCOMM
+** servers, and deallocates the service control block.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_deregister(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* set dealloc */
+ p_scb->dealloc = TRUE;
+
+ /* remove sdp records */
+ bta_ag_del_records(p_scb, p_data);
+
+ /* remove rfcomm servers */
+ bta_ag_close_servers(p_scb, p_scb->reg_services);
+
+ /* dealloc */
+ bta_ag_scb_dealloc(p_scb);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_start_dereg
+**
+** Description Start a deregister event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_start_dereg(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* set dealloc */
+ p_scb->dealloc = TRUE;
+
+ /* remove sdp records */
+ bta_ag_del_records(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_start_open
+**
+** Description This starts an AG open.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ BD_ADDR pending_bd_addr;
+
+ /* store parameters */
+ if (p_data)
+ {
+ bdcpy(p_scb->peer_addr, p_data->api_open.bd_addr);
+ p_scb->open_services = p_data->api_open.services;
+ p_scb->cli_sec_mask = p_data->api_open.sec_mask;
+ }
+
+ /* Check if RFCOMM has any incoming connection to avoid collision. */
+ if (PORT_IsOpening (pending_bd_addr))
+ {
+ /* Let the incoming connection goes through. */
+ /* Issue collision for this scb for now. */
+ /* We will decide what to do when we find incoming connetion later. */
+ bta_ag_collision_cback (0, BTA_ID_AG, 0, p_scb->peer_addr);
+ return;
+ }
+
+ /* close servers */
+ bta_ag_close_servers(p_scb, p_scb->reg_services);
+
+ /* set role */
+ p_scb->role = BTA_AG_INT;
+
+ /* do service search */
+ bta_ag_do_disc(p_scb, p_scb->open_services);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_disc_int_res
+**
+** Description This function handles a discovery result when initiator.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_disc_int_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ UINT16 event = BTA_AG_DISC_FAIL_EVT;
+
+ APPL_TRACE_DEBUG1 ("bta_ag_disc_int_res: Status: %d", p_data->disc_result.status);
+
+ /* if found service */
+ if (p_data->disc_result.status == SDP_SUCCESS ||
+ p_data->disc_result.status == SDP_DB_FULL)
+ {
+ /* get attributes */
+ if (bta_ag_sdp_find_attr(p_scb, p_scb->open_services))
+ {
+ /* set connected service */
+ p_scb->conn_service = bta_ag_service_to_idx(p_scb->open_services);
+
+ /* send ourselves sdp ok event */
+ event = BTA_AG_DISC_OK_EVT;
+ }
+ }
+
+ /* free discovery db */
+ bta_ag_free_db(p_scb, p_data);
+
+ /* if service not found check if we should search for other service */
+ if ((event == BTA_AG_DISC_FAIL_EVT) &&
+ (p_data->disc_result.status == SDP_SUCCESS ||
+ p_data->disc_result.status == SDP_DB_FULL ||
+ p_data->disc_result.status == SDP_NO_RECS_MATCH))
+ {
+ if ((p_scb->open_services & BTA_HFP_SERVICE_MASK) &&
+ (p_scb->open_services & BTA_HSP_SERVICE_MASK))
+ {
+ /* search for HSP */
+ p_scb->open_services &= ~BTA_HFP_SERVICE_MASK;
+ bta_ag_do_disc(p_scb, p_scb->open_services);
+ }
+ else if ((p_scb->open_services & BTA_HSP_SERVICE_MASK) &&
+ (p_scb->hsp_version == HSP_VERSION_1_2))
+ {
+ /* search for UUID_SERVCLASS_HEADSET for HSP 1.0 device */
+ p_scb->hsp_version = HSP_VERSION_1_0;
+ bta_ag_do_disc(p_scb, p_scb->open_services);
+ }
+ else
+ {
+ /* send ourselves sdp ok/fail event */
+ bta_ag_sm_execute(p_scb, event, p_data);
+ }
+ }
+ else
+ {
+ /* send ourselves sdp ok/fail event */
+ bta_ag_sm_execute(p_scb, event, p_data);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_disc_acp_res
+**
+** Description This function handles a discovery result when acceptor.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_disc_acp_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* if found service */
+ if (p_data->disc_result.status == SDP_SUCCESS ||
+ p_data->disc_result.status == SDP_DB_FULL)
+ {
+ /* get attributes */
+ bta_ag_sdp_find_attr(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
+ }
+
+ /* free discovery db */
+ bta_ag_free_db(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_disc_fail
+**
+** Description This function handles a discovery failure.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_disc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* reopen registered servers */
+ bta_ag_start_servers(p_scb, p_scb->reg_services);
+
+ /* reinitialize stuff */
+
+ /* call open cback w. failure */
+ bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_open_fail
+**
+** Description open connection failed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_open_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* call open cback w. failure */
+ bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_rfc_fail
+**
+** Description RFCOMM connection failed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* reinitialize stuff */
+ p_scb->conn_handle = 0;
+ p_scb->conn_service = 0;
+ p_scb->peer_features = 0;
+#if (BTM_WBS_INCLUDED == TRUE )
+ p_scb->peer_codecs = BTA_AG_CODEC_NONE;
+ p_scb->sco_codec = BTA_AG_CODEC_NONE;
+#endif
+ p_scb->role = 0;
+ p_scb->svc_conn = FALSE;
+ p_scb->hsp_version = HSP_VERSION_1_2;
+
+ /* reopen registered servers */
+ bta_ag_start_servers(p_scb, p_scb->reg_services);
+
+ /* call open cback w. failure */
+ bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_rfc_close
+**
+** Description RFCOMM connection closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ tBTA_AG_HDR close;
+ tBTA_SERVICE_MASK services;
+ int i, num_active_conn = 0;
+
+#ifdef _WIN32_WCE
+ /* The BTE RFCOMM automatically removes the connection when closed, but BTW does not */
+ if (p_scb->conn_handle != 0)
+ RFCOMM_RemoveConnection (p_scb->conn_handle);
+#endif
+
+ /* reinitialize stuff */
+ p_scb->conn_service = 0;
+ p_scb->peer_features = 0;
+#if (BTM_WBS_INCLUDED == TRUE )
+ p_scb->peer_codecs = BTA_AG_CODEC_NONE;
+ p_scb->sco_codec = BTA_AG_CODEC_NONE;
+#endif
+ p_scb->role = 0;
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ p_scb->svc_conn = FALSE;
+ p_scb->hsp_version = HSP_VERSION_1_2;
+ bta_ag_at_reinit(&p_scb->at_cb);
+
+ /* stop timers */
+ bta_sys_stop_timer(&p_scb->act_timer);
+#if (BTM_WBS_INCLUDED == TRUE)
+ bta_sys_stop_timer(&p_scb->cn_timer);
+#endif
+
+ close.handle = bta_ag_scb_to_idx(p_scb);
+ close.app_id = p_scb->app_id;
+
+ bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ /* call close call-out */
+ bta_ag_co_data_close(close.handle);
+
+ /* call close cback */
+ (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close);
+
+ /* if not deregistering (deallocating) reopen registered servers */
+ if (p_scb->dealloc == FALSE)
+ {
+ /* Clear peer bd_addr so instance can be reused */
+ bdcpy(p_scb->peer_addr, bd_addr_null);
+
+ /* start only unopened server */
+ services = p_scb->reg_services;
+ for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++)
+ {
+ if(p_scb->serv_handle[i])
+ services &= ~((tBTA_SERVICE_MASK)1 << (BTA_HSP_SERVICE_ID + i));
+ }
+ bta_ag_start_servers(p_scb, services);
+
+ p_scb->conn_handle = 0;
+
+ /* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */
+ bta_ag_sco_shutdown(p_scb, NULL);
+
+ /* Check if all the SLCs are down */
+ for (i = 0; i < BTA_AG_NUM_SCB; i++)
+ {
+ if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn)
+ num_active_conn++;
+ }
+
+ if(!num_active_conn)
+ {
+ bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+ }
+
+ }
+ /* else close port and deallocate scb */
+ else
+ {
+ RFCOMM_RemoveServer(p_scb->conn_handle);
+ bta_ag_scb_dealloc(p_scb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_rfc_open
+**
+** Description Handle RFCOMM channel open.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* initialize AT feature variables */
+ p_scb->clip_enabled = FALSE;
+ p_scb->ccwa_enabled = FALSE;
+ p_scb->cmer_enabled = FALSE;
+ p_scb->cmee_enabled = FALSE;
+ p_scb->inband_enabled = ((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND);
+
+ /* set up AT command interpreter */
+ p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD *) bta_ag_at_tbl[p_scb->conn_service];
+ p_scb->at_cb.p_cmd_cback = (tBTA_AG_AT_CMD_CBACK *) bta_ag_at_cback_tbl[p_scb->conn_service];
+ p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK *) bta_ag_at_err_cback;
+ p_scb->at_cb.p_user = p_scb;
+ p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX;
+ bta_ag_at_init(&p_scb->at_cb);
+
+ /* call app open call-out */
+ bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb), bta_ag_svc_id[p_scb->conn_service]);
+
+ bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS);
+
+ if (p_scb->conn_service == BTA_AG_HFP)
+ {
+ /* if hfp start timer for service level conn */
+ bta_sys_start_timer(&p_scb->act_timer, BTA_AG_SVC_TOUT_EVT, p_bta_ag_cfg->conn_tout);
+ }
+ else
+ {
+ /* else service level conn is open */
+ bta_ag_svc_conn_open(p_scb, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_rfc_acp_open
+**
+** Description Handle RFCOMM channel open when accepting connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ UINT16 lcid;
+ int i;
+ tBTA_AG_SCB *ag_scb, *other_scb;
+ BD_ADDR dev_addr;
+ int status;
+
+ /* set role */
+ p_scb->role = BTA_AG_ACP;
+
+ APPL_TRACE_DEBUG2 ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
+ p_scb->serv_handle[0], p_scb->serv_handle[1]);
+
+ /* get bd addr of peer */
+ if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid)))
+ {
+ APPL_TRACE_DEBUG1 ("bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d", status);
+ }
+
+ /* Collision Handling */
+ for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
+ {
+ if ((ag_scb->in_use) && (ag_scb->colli_tmr_on))
+ {
+ /* stop collision timer */
+ ag_scb->colli_tmr_on = FALSE;
+ bta_sys_stop_timer (&ag_scb->colli_timer);
+
+ if (bdcmp (dev_addr, ag_scb->peer_addr) == 0)
+ {
+ /* If incoming and outgoing device are same, nothing more to do. */
+ /* Outgoing conn will be aborted because we have successful incoming conn. */
+ }
+ else
+ {
+ /* Resume outgoing connection. */
+ other_scb = bta_ag_get_other_idle_scb (p_scb);
+ if (other_scb)
+ {
+ bdcpy(other_scb->peer_addr, ag_scb->peer_addr);
+ other_scb->open_services = ag_scb->open_services;
+ other_scb->cli_sec_mask = ag_scb->cli_sec_mask;
+
+ bta_ag_resume_open (other_scb);
+ }
+ }
+
+ break;
+ }
+ }
+
+ bdcpy (p_scb->peer_addr, dev_addr);
+
+ /* determine connected service from port handle */
+ for (i = 0; i < BTA_AG_NUM_IDX; i++)
+ {
+ APPL_TRACE_DEBUG3 ("bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d",
+ i, p_scb->serv_handle[i], p_data->rfc.port_handle);
+
+ if (p_scb->serv_handle[i] == p_data->rfc.port_handle)
+ {
+ p_scb->conn_service = i;
+ p_scb->conn_handle = p_data->rfc.port_handle;
+ break;
+ }
+ }
+
+ APPL_TRACE_DEBUG2 ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d",
+ p_scb->conn_service, p_scb->conn_handle);
+
+ /* close any unopened server */
+ bta_ag_close_servers(p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service]));
+
+ /* do service discovery to get features */
+ bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
+
+ /* continue with common open processing */
+ bta_ag_rfc_open(p_scb, p_data);
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_rfc_data
+**
+** Description Read and process data from RFCOMM.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ UINT16 len;
+ char buf[BTA_AG_RFC_READ_MAX];
+
+ memset(buf, 0, BTA_AG_RFC_READ_MAX);
+
+ /* do the following */
+ for(;;)
+ {
+ /* read data from rfcomm; if bad status, we're done */
+ if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) != PORT_SUCCESS)
+ {
+ break;
+ }
+
+ /* if no data, we're done */
+ if (len == 0)
+ {
+ break;
+ }
+
+ /* run AT command interpreter on data */
+ bta_ag_at_parse(&p_scb->at_cb, buf, len);
+
+ /* no more data to read, we're done */
+ if (len < BTA_AG_RFC_READ_MAX)
+ {
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_start_close
+**
+** Description Start the process of closing SCO and RFCOMM connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* Take the link out of sniff and set L2C idle time to 0 */
+ bta_dm_pm_active(p_scb->peer_addr);
+ L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0);
+
+ /* if SCO is open close SCO and wait on RFCOMM close */
+ if (bta_ag_sco_is_open(p_scb))
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC;
+ }
+ else
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ bta_ag_rfc_do_close(p_scb, p_data);
+ }
+
+ /* always do SCO shutdown to handle all SCO corner cases */
+ bta_ag_sco_shutdown(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_post_sco_open
+**
+** Description Perform post-SCO open action, if any
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_post_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ switch (p_scb->post_sco)
+ {
+ case BTA_AG_POST_SCO_RING:
+ bta_ag_send_ring(p_scb, p_data);
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ break;
+
+ case BTA_AG_POST_SCO_CALL_CONN:
+ bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_post_sco_close
+**
+** Description Perform post-SCO close action, if any
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_post_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ switch (p_scb->post_sco)
+ {
+ case BTA_AG_POST_SCO_CLOSE_RFC:
+ bta_ag_rfc_do_close(p_scb, p_data);
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ break;
+
+ case BTA_AG_POST_SCO_CALL_CONN:
+ bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ break;
+
+ case BTA_AG_POST_SCO_CALL_ORIG:
+ bta_ag_send_call_inds(p_scb, BTA_AG_OUT_CALL_ORIG_RES);
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ break;
+
+ case BTA_AG_POST_SCO_CALL_END:
+ bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ break;
+
+ case BTA_AG_POST_SCO_CALL_END_INCALL:
+ bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
+
+ /* Sending callsetup IND and Ring were defered to after SCO close. */
+ bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_RES);
+
+ if (bta_ag_inband_enabled(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_RING;
+ bta_ag_sco_open(p_scb, p_data);
+ }
+ else
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ bta_ag_send_ring(p_scb, p_data);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_svc_conn_open
+**
+** Description Service level connection opened
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ tBTA_AG_CONN evt;
+
+ if (!p_scb->svc_conn)
+ {
+ /* set state variable */
+ p_scb->svc_conn = TRUE;
+
+ /* Clear AT+BIA mask from previous SLC if any. */
+ p_scb->bia_masked_out = 0;
+
+ /* stop timer */
+ bta_sys_stop_timer(&p_scb->act_timer);
+
+ /* call callback */
+ evt.hdr.handle = bta_ag_scb_to_idx(p_scb);
+ evt.hdr.app_id = p_scb->app_id;
+ evt.peer_feat = p_scb->peer_features;
+#if (BTM_WBS_INCLUDED == TRUE )
+ evt.peer_codec = p_scb->peer_codecs;
+#endif
+
+ if ((p_scb->call_ind != BTA_AG_CALL_INACTIVE) ||
+ (p_scb->callsetup_ind != BTA_AG_CALLSETUP_NONE))
+ {
+ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+ }
+
+ (*bta_ag_cb.p_cback)(BTA_AG_CONN_EVT, (tBTA_AG *) &evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_ci_rx_data
+**
+** Description Send result code
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ UINT16 len;
+ tBTA_AG_CI_RX_WRITE *p_rx_write_msg = (tBTA_AG_CI_RX_WRITE *)p_data;
+ char *p_data_area = (char *)(p_rx_write_msg+1); /* Point to data area after header */
+
+ /* send to RFCOMM */
+ PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_rcvd_slc_ready
+**
+** Description Handles SLC ready call-in in case of pass-through mode.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1("bta_ag_rcvd_slc_ready: handle = %d", bta_ag_scb_to_idx(p_scb));
+
+ if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH)
+ {
+ /* In pass-through mode, BTA knows that SLC is ready only through call-in. */
+ bta_ag_svc_conn_open(p_scb, NULL);
+ }
+}
+
diff --git a/bta/ag/bta_ag_api.c b/bta/ag/bta_ag_api.c
new file mode 100644
index 0000000..07dceb9
--- /dev/null
+++ b/bta/ag/bta_ag_api.c
@@ -0,0 +1,323 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation of the API for the audio gateway (AG)
+ * subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ * phones.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "gki.h"
+#include <string.h>
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_ag_reg =
+{
+ bta_ag_hdl_event,
+ BTA_AgDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_AgEnable
+**
+** Description Enable the audio gateway service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_AG_ENABLE_EVT. This function must
+** be called before other function in the AG API are
+** called.
+**
+** Returns BTA_SUCCESS if OK, BTA_FAILURE otherwise.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_AgEnable(tBTA_AG_PARSE_MODE parse_mode, tBTA_AG_CBACK *p_cback)
+{
+ tBTA_AG_API_ENABLE *p_buf;
+ UINT8 idx;
+
+ /* Error if AG is already enabled, or AG is in the middle of disabling. */
+ for (idx = 0; idx < BTA_AG_NUM_SCB; idx++)
+ {
+ if (bta_ag_cb.scb[idx].in_use)
+ {
+ APPL_TRACE_ERROR0 ("BTA_AgEnable: FAILED, AG already enabled.");
+ return BTA_FAILURE;
+ }
+ }
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_AG, &bta_ag_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_AG_API_ENABLE *) GKI_getbuf(sizeof(tBTA_AG_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AG_API_ENABLE_EVT;
+ p_buf->parse_mode = parse_mode;
+ p_buf->p_cback = p_cback;
+ bta_sys_sendmsg(p_buf);
+ }
+
+ return BTA_SUCCESS;
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_AgDisable
+**
+** Description Disable the audio gateway service
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgDisable(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AG_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AgRegister
+**
+** Description Register an Audio Gateway service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgRegister(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,tBTA_AG_FEAT features,
+ char * p_service_names[], UINT8 app_id)
+{
+ tBTA_AG_API_REGISTER *p_buf;
+ int i;
+
+ if ((p_buf = (tBTA_AG_API_REGISTER *) GKI_getbuf(sizeof(tBTA_AG_API_REGISTER))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AG_API_REGISTER_EVT;
+ p_buf->features = features;
+ p_buf->sec_mask = sec_mask;
+ p_buf->services = services;
+ p_buf->app_id = app_id;
+ for (i = 0; i < BTA_AG_NUM_IDX; i++)
+ {
+ if(p_service_names[i])
+ {
+ BCM_STRNCPY_S(p_buf->p_name[i], BTA_SERVICE_NAME_LEN+1, p_service_names[i], BTA_SERVICE_NAME_LEN);
+ p_buf->p_name[i][BTA_SERVICE_NAME_LEN] = 0;
+ }
+ else
+ {
+ p_buf->p_name[i][0] = 0;
+ }
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AgDeregister
+**
+** Description Deregister an audio gateway service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgDeregister(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AG_API_DEREGISTER_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AgOpen
+**
+** Description Opens a connection to a headset or hands-free device.
+** When connection is open callback function is called
+** with a BTA_AG_OPEN_EVT. Only the data connection is
+** opened. The audio connection is not opened.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgOpen(UINT16 handle, BD_ADDR bd_addr, tBTA_SEC sec_mask, tBTA_SERVICE_MASK services)
+{
+ tBTA_AG_API_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_AG_API_OPEN *) GKI_getbuf(sizeof(tBTA_AG_API_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AG_API_OPEN_EVT;
+ p_buf->hdr.layer_specific = handle;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ p_buf->services = services;
+ p_buf->sec_mask = sec_mask;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AgClose
+**
+** Description Close the current connection to a headset or a handsfree
+** Any current audio connection will also be closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgClose(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AG_API_CLOSE_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AgAudioOpen
+**
+** Description Opens an audio connection to the currently connected
+** headset or hnadsfree.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgAudioOpen(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AG_API_AUDIO_OPEN_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AgAudioClose
+**
+** Description Close the currently active audio connection to a headset
+** or hnadsfree. The data connection remains open
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgAudioClose(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AG_API_AUDIO_CLOSE_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_AgResult
+**
+** Description Send an AT result code to a headset or hands-free device.
+** This function is only used when the AG parse mode is set
+** to BTA_AG_PARSE.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgResult(UINT16 handle, tBTA_AG_RES result, tBTA_AG_RES_DATA *p_data)
+{
+ tBTA_AG_API_RESULT *p_buf;
+
+ if ((p_buf = (tBTA_AG_API_RESULT *) GKI_getbuf(sizeof(tBTA_AG_API_RESULT))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AG_API_RESULT_EVT;
+ p_buf->hdr.layer_specific = handle;
+ p_buf->result = result;
+ if(p_data)
+ {
+ memcpy(&p_buf->data, p_data, sizeof(p_buf->data));
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AgSetCodec
+**
+** Description Specify the codec type to be used for the subsequent
+** audio connection.
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec)
+{
+ tBTA_AG_API_SETCODEC *p_buf;
+
+ if ((p_buf = (tBTA_AG_API_SETCODEC *) GKI_getbuf(sizeof(tBTA_AG_API_SETCODEC))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AG_API_SETCODEC_EVT;
+ p_buf->hdr.layer_specific = handle;
+ p_buf->codec = codec;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
diff --git a/bta/ag/bta_ag_at.c b/bta/ag/bta_ag_at.c
new file mode 100644
index 0000000..74d3948
--- /dev/null
+++ b/bta/ag/bta_ag_at.c
@@ -0,0 +1,243 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * BTA AG AT command interpreter.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "gki.h"
+#include "bta_ag_at.h"
+#include "utl.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/******************************************************************************
+**
+** Function bta_ag_at_init
+**
+** Description Initialize the AT command parser control block.
+**
+**
+** Returns void
+**
+******************************************************************************/
+void bta_ag_at_init(tBTA_AG_AT_CB *p_cb)
+{
+ p_cb->p_cmd_buf = NULL;
+ p_cb->cmd_pos = 0;
+}
+
+/******************************************************************************
+**
+** Function bta_ag_at_reinit
+**
+** Description Re-initialize the AT command parser control block. This
+** function resets the AT command parser state and frees
+** any GKI buffer.
+**
+**
+** Returns void
+**
+******************************************************************************/
+void bta_ag_at_reinit(tBTA_AG_AT_CB *p_cb)
+{
+ if (p_cb->p_cmd_buf != NULL)
+ {
+ GKI_freebuf(p_cb->p_cmd_buf);
+ p_cb->p_cmd_buf = NULL;
+ }
+ p_cb->cmd_pos = 0;
+}
+/******************************************************************************
+**
+** Function bta_ag_process_at
+**
+** Description Parse AT commands. This function will take the input
+** character string and parse it for AT commands according to
+** the AT command table passed in the control block.
+**
+**
+** Returns void
+**
+******************************************************************************/
+void bta_ag_process_at(tBTA_AG_AT_CB *p_cb)
+{
+ UINT16 idx;
+ UINT8 arg_type;
+ char *p_arg;
+ INT16 int_arg = 0;
+ /* loop through at command table looking for match */
+ for (idx = 0; p_cb->p_at_tbl[idx].p_cmd[0] != 0; idx++)
+ {
+ if (!utl_strucmp(p_cb->p_at_tbl[idx].p_cmd, p_cb->p_cmd_buf))
+ {
+ break;
+ }
+ }
+
+ /* if there is a match; verify argument type */
+ if (p_cb->p_at_tbl[idx].p_cmd[0] != 0)
+ {
+ /* start of argument is p + strlen matching command */
+ p_arg = p_cb->p_cmd_buf + strlen(p_cb->p_at_tbl[idx].p_cmd);
+
+ /* if no argument */
+ if (p_arg[0] == 0)
+ {
+ arg_type = BTA_AG_AT_NONE;
+ }
+ /* else if arg is '?' and it is last character */
+ else if (p_arg[0] == '?' && p_arg[1] == 0)
+ {
+ /* we have a read */
+ arg_type = BTA_AG_AT_READ;
+ }
+ /* else if arg is '=' */
+ else if (p_arg[0] == '=' && p_arg[1] != 0)
+ {
+ if (p_arg[1] == '?' && p_arg[2] == 0)
+ {
+ /* we have a test */
+ arg_type = BTA_AG_AT_TEST;
+ }
+ else
+ {
+ /* we have a set */
+ arg_type = BTA_AG_AT_SET;
+
+ /* skip past '=' */
+ p_arg++;
+ }
+ }
+ else
+ /* else it is freeform argument */
+ {
+ arg_type = BTA_AG_AT_FREE;
+ }
+
+ /* if arguments match command capabilities */
+ if ((arg_type & p_cb->p_at_tbl[idx].arg_type) != 0)
+ {
+ /* if it's a set integer check max, min range */
+ if (arg_type == BTA_AG_AT_SET &&
+ p_cb->p_at_tbl[idx].fmt == BTA_AG_AT_INT)
+ {
+ int_arg = utl_str2int(p_arg);
+ if (int_arg < (INT16) p_cb->p_at_tbl[idx].min ||
+ int_arg > (INT16) p_cb->p_at_tbl[idx].max)
+ {
+ /* arg out of range; error */
+ (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
+ }
+ else
+ {
+
+ (*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
+ }
+ }
+ else
+ {
+ (*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
+ }
+ }
+ /* else error */
+ else
+ {
+ (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
+ }
+ }
+ /* else no match call error callback */
+ else
+ {
+ (*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
+ }
+}
+
+/******************************************************************************
+**
+** Function bta_ag_at_parse
+**
+** Description Parse AT commands. This function will take the input
+** character string and parse it for AT commands according to
+** the AT command table passed in the control block.
+**
+**
+** Returns void
+**
+******************************************************************************/
+void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len)
+{
+ int i = 0;
+ char* p_save;
+
+ if (p_cb->p_cmd_buf == NULL)
+ {
+ p_cb->p_cmd_buf = (char *) GKI_getbuf(p_cb->cmd_max_len);
+ p_cb->cmd_pos = 0;
+ }
+
+ for (i = 0; i < len;)
+ {
+ while (p_cb->cmd_pos < p_cb->cmd_max_len-1 && i < len)
+ {
+ /* Skip null characters between AT commands. */
+ if ((p_cb->cmd_pos == 0) && (p_buf[i] == 0))
+ {
+ i++;
+ continue;
+ }
+
+ p_cb->p_cmd_buf[p_cb->cmd_pos] = p_buf[i++];
+ if ( p_cb->p_cmd_buf[p_cb->cmd_pos] == '\r' || p_cb->p_cmd_buf[p_cb->cmd_pos] == '\n')
+ {
+ p_cb->p_cmd_buf[p_cb->cmd_pos] = 0;
+ if ((p_cb->cmd_pos > 2) &&
+ (p_cb->p_cmd_buf[0] == 'A' || p_cb->p_cmd_buf[0] == 'a') &&
+ (p_cb->p_cmd_buf[1] == 'T' || p_cb->p_cmd_buf[1] == 't'))
+ {
+ p_save = p_cb->p_cmd_buf;
+ p_cb->p_cmd_buf += 2;
+ bta_ag_process_at(p_cb);
+ p_cb->p_cmd_buf = p_save;
+ }
+
+ p_cb->cmd_pos = 0;
+
+ }
+ else if( p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1A || p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1B )
+ {
+ p_cb->p_cmd_buf[++p_cb->cmd_pos] = 0;
+ (*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
+ p_cb->cmd_pos = 0;
+ }
+ else
+ {
+ ++p_cb->cmd_pos;
+ }
+ }
+
+ if (i < len)
+ p_cb->cmd_pos = 0;
+ }
+}
+
diff --git a/bta/ag/bta_ag_at.h b/bta/ag/bta_ag_at.h
new file mode 100644
index 0000000..90d7b0f
--- /dev/null
+++ b/bta/ag/bta_ag_at.h
@@ -0,0 +1,121 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Interface file for BTA AG AT command interpreter.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_AT_H
+#define BTA_AG_AT_H
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/* AT command argument capabilities */
+#define BTA_AG_AT_NONE 0x01 /* no argument */
+#define BTA_AG_AT_SET 0x02 /* set value */
+#define BTA_AG_AT_READ 0x04 /* read value */
+#define BTA_AG_AT_TEST 0x08 /* test value range */
+#define BTA_AG_AT_FREE 0x10 /* freeform argument */
+
+/* AT command argument format */
+#define BTA_AG_AT_STR 0 /* string */
+#define BTA_AG_AT_INT 1 /* integer */
+
+/*****************************************************************************
+** Data types
+*****************************************************************************/
+
+/* AT command table element */
+typedef struct
+{
+ const char *p_cmd; /* AT command string */
+ UINT8 arg_type; /* allowable argument type syntax */
+ UINT8 fmt; /* whether arg is int or string */
+ UINT8 min; /* minimum value for int arg */
+ INT16 max; /* maximum value for int arg */
+} tBTA_AG_AT_CMD;
+
+/* callback function executed when command is parsed */
+typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 cmd, UINT8 arg_type,
+ char *p_arg, INT16 int_arg);
+
+/* callback function executed to send "ERROR" result code */
+typedef void (tBTA_AG_AT_ERR_CBACK)(void *p_user, BOOLEAN unknown, char *p_arg);
+
+/* AT command parsing control block */
+typedef struct
+{
+ tBTA_AG_AT_CMD *p_at_tbl; /* AT command table */
+ tBTA_AG_AT_CMD_CBACK *p_cmd_cback; /* command callback */
+ tBTA_AG_AT_ERR_CBACK *p_err_cback; /* error callback */
+ void *p_user; /* user-defined data */
+ char *p_cmd_buf; /* temp parsing buffer */
+ UINT16 cmd_pos; /* position in temp buffer */
+ UINT16 cmd_max_len; /* length of temp buffer to allocate */
+ UINT8 state; /* parsing state */
+} tBTA_AG_AT_CB;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+/*****************************************************************************
+**
+** Function bta_ag_at_init
+**
+** Description Initialize the AT command parser control block.
+**
+**
+** Returns void
+**
+*****************************************************************************/
+extern void bta_ag_at_init(tBTA_AG_AT_CB *p_cb);
+
+/*****************************************************************************
+**
+** Function bta_ag_at_reinit
+**
+** Description Re-initialize the AT command parser control block. This
+** function resets the AT command parser state and frees
+** any GKI buffer.
+**
+**
+** Returns void
+**
+*****************************************************************************/
+extern void bta_ag_at_reinit(tBTA_AG_AT_CB *p_cb);
+
+/*****************************************************************************
+**
+** Function bta_ag_at_parse
+**
+** Description Parse AT commands. This function will take the input
+** character string and parse it for AT commands according to
+** the AT command table passed in the control block.
+**
+**
+** Returns void
+**
+*****************************************************************************/
+extern void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len);
+
+#endif /* BTA_AG_AT_H */
+
diff --git a/bta/ag/bta_ag_cfg.c b/bta/ag/bta_ag_cfg.c
new file mode 100644
index 0000000..e02f9f6
--- /dev/null
+++ b/bta/ag/bta_ag_cfg.c
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains compile-time configurable constants for the audio
+ * gateway.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bta_api.h"
+#include "bta_ag_api.h"
+
+#ifndef BTA_AG_CIND_INFO
+#define BTA_AG_CIND_INFO "(\"call\",(0,1)),(\"callsetup\",(0-3)),(\"service\",(0-3)),(\"signal\",(0-6)),(\"roam\",(0,1)),(\"battchg\",(0-5)),(\"callheld\",(0-2)),(\"bearer\",(0-7))"
+#endif
+
+#ifndef BTA_AG_CHLD_VAL_ECC
+#define BTA_AG_CHLD_VAL_ECC "(0,1,1x,2,2x,3,4)"
+#endif
+
+#ifndef BTA_AG_CHLD_VAL
+#define BTA_AG_CHLD_VAL "(0,1,2,3,4)"
+#endif
+
+#ifndef BTA_AG_CONN_TIMEOUT
+#define BTA_AG_CONN_TIMEOUT 5000
+#endif
+
+#ifndef BTA_AG_SCO_PKT_TYPES
+/* S1 packet type setting from HFP 1.5 spec */
+#define BTA_AG_SCO_PKT_TYPES /* BTM_SCO_LINK_ALL_PKT_MASK */ (BTM_SCO_LINK_ONLY_MASK | \
+ BTM_SCO_PKT_TYPES_MASK_EV3 | \
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
+#endif
+
+const tBTA_AG_CFG bta_ag_cfg =
+{
+ BTA_AG_CIND_INFO,
+ BTA_AG_CONN_TIMEOUT,
+ BTA_AG_SCO_PKT_TYPES,
+ BTA_AG_CHLD_VAL_ECC,
+ BTA_AG_CHLD_VAL
+};
+
+tBTA_AG_CFG *p_bta_ag_cfg = (tBTA_AG_CFG *) &bta_ag_cfg;
diff --git a/bta/ag/bta_ag_ci.c b/bta/ag/bta_ag_ci.c
new file mode 100644
index 0000000..fd39e34
--- /dev/null
+++ b/bta/ag/bta_ag_ci.c
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation file for audio gateway call-in functions.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "bta_ag_ci.h"
+#include "gki.h"
+
+/******************************************************************************
+**
+** Function bta_ag_ci_rx_write
+**
+** Description This function is called to send data to the AG when the AG
+** is configured for AT command pass-through. The function
+** copies data to an event buffer and sends it.
+**
+** Returns void
+**
+******************************************************************************/
+void bta_ag_ci_rx_write(UINT16 handle, char *p_data, UINT16 len)
+{
+ tBTA_AG_CI_RX_WRITE *p_buf;
+ UINT16 len_remaining = len;
+ char *p_data_area;
+
+ if (len > (RFCOMM_DATA_POOL_BUF_SIZE - sizeof(tBTA_AG_CI_RX_WRITE) - 1))
+ len = RFCOMM_DATA_POOL_BUF_SIZE - sizeof(tBTA_AG_CI_RX_WRITE) - 1;
+
+ while (len_remaining)
+ {
+ if (len_remaining < len)
+ len = len_remaining;
+
+ if ((p_buf = (tBTA_AG_CI_RX_WRITE *) GKI_getbuf((UINT16)(sizeof(tBTA_AG_CI_RX_WRITE) + len + 1))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AG_CI_RX_WRITE_EVT;
+ p_buf->hdr.layer_specific = handle;
+
+ p_data_area = (char *)(p_buf+1); /* Point to data area after header */
+ strncpy(p_data_area, p_data, len);
+ p_data_area[len] = 0;
+
+ bta_sys_sendmsg(p_buf);
+ } else {
+ APPL_TRACE_ERROR1("ERROR: Unable to allocate buffer to hold AT response code. len=%i", len);
+ break;
+ }
+
+ len_remaining-=len;
+ p_data+=len;
+ }
+}
+
+/******************************************************************************
+**
+** Function bta_ag_ci_slc_ready
+**
+** Description This function is called to notify AG that SLC is up at
+** the application. This funcion is only used when the app
+** is running in pass-through mode.
+**
+** Returns void
+**
+******************************************************************************/
+void bta_ag_ci_slc_ready(UINT16 handle)
+{
+ tBTA_AG_DATA *p_buf;
+
+ if ((p_buf = (tBTA_AG_DATA *)GKI_getbuf(sizeof(tBTA_AG_DATA))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AG_CI_SLC_READY_EVT;
+ p_buf->hdr.layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
diff --git a/bta/ag/bta_ag_cmd.c b/bta/ag/bta_ag_cmd.c
new file mode 100644
index 0000000..d552eed
--- /dev/null
+++ b/bta/ag/bta_ag_cmd.c
@@ -0,0 +1,1836 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains functions for processing AT commands and results.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "bta_ag_at.h"
+#include "port_api.h"
+#include "utl.h"
+#include <stdio.h>
+#include <string.h>
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/* ring timeout */
+#define BTA_AG_RING_TOUT 10000
+
+#define BTA_AG_CMD_MAX_VAL 32767 /* Maximum value is signed 16-bit value */
+
+
+
+/* clip type constants */
+#define BTA_AG_CLIP_TYPE_MIN 128
+#define BTA_AG_CLIP_TYPE_MAX 175
+#define BTA_AG_CLIP_TYPE_DEFAULT 129
+#define BTA_AG_CLIP_TYPE_VOIP 255
+
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+#define BTA_AG_AT_MULTI_LEN 2
+#define AT_SET_RES_CB(res_cb, c, p, i) {res_cb.code = c; res_cb.p_arg = p; res_cb.int_arg = i;}
+
+/* type for AT result code block */
+typedef struct
+{
+ UINT8 code;
+ char *p_arg;
+ INT16 int_arg;
+} tBTA_AG_RESULT_CB;
+
+/* type for multiple AT result codes block */
+typedef struct
+{
+ UINT8 num_result;
+ tBTA_AG_RESULT_CB res_cb[BTA_AG_AT_MULTI_LEN];
+} tBTA_AG_MULTI_RESULT_CB;
+#endif
+
+/* enumeration of HSP AT commands matches HSP command interpreter table */
+enum
+{
+ BTA_AG_HS_CMD_CKPD,
+ BTA_AG_HS_CMD_VGS,
+ BTA_AG_HS_CMD_VGM
+};
+
+/* enumeration of HFP AT commands matches HFP command interpreter table */
+enum
+{
+ BTA_AG_HF_CMD_A,
+ BTA_AG_HF_CMD_D,
+ BTA_AG_HF_CMD_VGS,
+ BTA_AG_HF_CMD_VGM,
+ BTA_AG_HF_CMD_CCWA,
+ BTA_AG_HF_CMD_CHLD,
+ BTA_AG_HF_CMD_CHUP,
+ BTA_AG_HF_CMD_CIND,
+ BTA_AG_HF_CMD_CLIP,
+ BTA_AG_HF_CMD_CMER,
+ BTA_AG_HF_CMD_VTS,
+ BTA_AG_HF_CMD_BINP,
+ BTA_AG_HF_CMD_BLDN,
+ BTA_AG_HF_CMD_BVRA,
+ BTA_AG_HF_CMD_BRSF,
+ BTA_AG_HF_CMD_NREC,
+ BTA_AG_HF_CMD_CNUM,
+ BTA_AG_HF_CMD_BTRH,
+ BTA_AG_HF_CMD_CLCC,
+ BTA_AG_HF_CMD_COPS,
+ BTA_AG_HF_CMD_CMEE,
+ BTA_AG_HF_CMD_BIA,
+ BTA_AG_HF_CMD_CBC,
+ BTA_AG_HF_CMD_BCC,
+ BTA_AG_HF_CMD_BCS,
+ BTA_AG_HF_CMD_BAC
+};
+
+/* AT command interpreter table for HSP */
+const tBTA_AG_AT_CMD bta_ag_hsp_cmd[] =
+{
+ {"+CKPD", BTA_AG_AT_SET, BTA_AG_AT_INT, 200, 200},
+ {"+VGS", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
+ {"+VGM", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
+ {"", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}
+};
+
+/* AT command interpreter table for HFP */
+const tBTA_AG_AT_CMD bta_ag_hfp_cmd[] =
+{
+ {"A", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"D", (BTA_AG_AT_NONE | BTA_AG_AT_FREE), BTA_AG_AT_STR, 0, 0},
+ {"+VGS", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
+ {"+VGM", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 15},
+ {"+CCWA", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
+ /* Consider CHLD as str to take care of indexes for ECC */
+ {"+CHLD", (BTA_AG_AT_SET | BTA_AG_AT_TEST), BTA_AG_AT_STR, 0, 4},
+ {"+CHUP", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+CIND", (BTA_AG_AT_READ | BTA_AG_AT_TEST), BTA_AG_AT_STR, 0, 0},
+ {"+CLIP", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
+ {"+CMER", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
+ {"+VTS", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
+ {"+BINP", BTA_AG_AT_SET, BTA_AG_AT_INT, 1, 1},
+ {"+BLDN", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+BVRA", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
+ {"+BRSF", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, BTA_AG_CMD_MAX_VAL},
+ {"+NREC", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 0},
+ {"+CNUM", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+BTRH", (BTA_AG_AT_READ | BTA_AG_AT_SET), BTA_AG_AT_INT, 0, 2},
+ {"+CLCC", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+COPS", (BTA_AG_AT_READ | BTA_AG_AT_SET), BTA_AG_AT_STR, 0, 0},
+ {"+CMEE", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 1},
+ {"+BIA", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 20},
+ {"+CBC", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, 100},
+ {"+BCC", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0},
+ {"+BCS", BTA_AG_AT_SET, BTA_AG_AT_INT, 0, BTA_AG_CMD_MAX_VAL},
+ {"+BAC", BTA_AG_AT_SET, BTA_AG_AT_STR, 0, 0},
+ {"", BTA_AG_AT_NONE, BTA_AG_AT_STR, 0, 0}
+};
+
+/* AT result code table element */
+typedef struct
+{
+ const char *p_res; /* AT result string */
+ UINT8 fmt; /* whether argument is int or string */
+} tBTA_AG_RESULT;
+
+/* AT result code argument types */
+enum
+{
+ BTA_AG_RES_FMT_NONE, /* no argument */
+ BTA_AG_RES_FMT_INT, /* integer argument */
+ BTA_AG_RES_FMT_STR /* string argument */
+};
+
+/* enumeration of AT result codes, matches constant table */
+enum
+{
+ BTA_AG_RES_OK,
+ BTA_AG_RES_ERROR,
+ BTA_AG_RES_RING,
+ BTA_AG_RES_VGS,
+ BTA_AG_RES_VGM,
+ BTA_AG_RES_CCWA,
+ BTA_AG_RES_CHLD,
+ BTA_AG_RES_CIND,
+ BTA_AG_RES_CLIP,
+ BTA_AG_RES_CIEV,
+ BTA_AG_RES_BINP,
+ BTA_AG_RES_BVRA,
+ BTA_AG_RES_BRSF,
+ BTA_AG_RES_BSIR,
+ BTA_AG_RES_CNUM,
+ BTA_AG_RES_BTRH,
+ BTA_AG_RES_CLCC,
+ BTA_AG_RES_COPS,
+ BTA_AG_RES_CMEE,
+ BTA_AG_RES_BCS,
+ BTA_AG_RES_UNAT
+};
+
+#if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
+#define COLON_IDX_4_VGSVGM 4
+#endif
+/* AT result code constant table (Indexed by result code) */
+const tBTA_AG_RESULT bta_ag_result_tbl[] =
+{
+ {"OK", BTA_AG_RES_FMT_NONE},
+ {"ERROR", BTA_AG_RES_FMT_NONE},
+ {"RING", BTA_AG_RES_FMT_NONE},
+ {"+VGS: ", BTA_AG_RES_FMT_INT},
+ {"+VGM: ", BTA_AG_RES_FMT_INT},
+ {"+CCWA: ", BTA_AG_RES_FMT_STR},
+ {"+CHLD: ", BTA_AG_RES_FMT_STR},
+ {"+CIND: ", BTA_AG_RES_FMT_STR},
+ {"+CLIP: ", BTA_AG_RES_FMT_STR},
+ {"+CIEV: ", BTA_AG_RES_FMT_STR},
+ {"+BINP: ", BTA_AG_RES_FMT_STR},
+ {"+BVRA: ", BTA_AG_RES_FMT_INT},
+ {"+BRSF: ", BTA_AG_RES_FMT_INT},
+ {"+BSIR: ", BTA_AG_RES_FMT_INT},
+ {"+CNUM: ", BTA_AG_RES_FMT_STR},
+ {"+BTRH: ", BTA_AG_RES_FMT_INT},
+ {"+CLCC: ", BTA_AG_RES_FMT_STR},
+ {"+COPS: ", BTA_AG_RES_FMT_STR},
+ {"+CME ERROR: ", BTA_AG_RES_FMT_INT},
+ {"+BCS: ", BTA_AG_RES_FMT_INT},
+ {"", BTA_AG_RES_FMT_STR}
+};
+
+const tBTA_AG_AT_CMD *bta_ag_at_tbl[BTA_AG_NUM_IDX] =
+{
+ bta_ag_hsp_cmd,
+ bta_ag_hfp_cmd
+};
+
+/* callback event lookup table for HSP */
+const tBTA_AG_EVT bta_ag_hsp_cb_evt[] =
+{
+ BTA_AG_AT_CKPD_EVT, /* BTA_AG_HS_CMD_CKPD */
+ BTA_AG_SPK_EVT, /* BTA_AG_HS_CMD_VGS */
+ BTA_AG_MIC_EVT /* BTA_AG_HS_CMD_VGM */
+};
+
+/* callback event lookup table for HFP (Indexed by command) */
+const tBTA_AG_EVT bta_ag_hfp_cb_evt[] =
+{
+ BTA_AG_AT_A_EVT, /* BTA_AG_HF_CMD_A */
+ BTA_AG_AT_D_EVT, /* BTA_AG_HF_CMD_D */
+ BTA_AG_SPK_EVT, /* BTA_AG_HF_CMD_VGS */
+ BTA_AG_MIC_EVT, /* BTA_AG_HF_CMD_VGM */
+ 0, /* BTA_AG_HF_CMD_CCWA */
+ BTA_AG_AT_CHLD_EVT, /* BTA_AG_HF_CMD_CHLD */
+ BTA_AG_AT_CHUP_EVT, /* BTA_AG_HF_CMD_CHUP */
+ BTA_AG_AT_CIND_EVT, /* BTA_AG_HF_CMD_CIND */
+ 0, /* BTA_AG_HF_CMD_CLIP */
+ 0, /* BTA_AG_HF_CMD_CMER */
+ BTA_AG_AT_VTS_EVT, /* BTA_AG_HF_CMD_VTS */
+ BTA_AG_AT_BINP_EVT, /* BTA_AG_HF_CMD_BINP */
+ BTA_AG_AT_BLDN_EVT, /* BTA_AG_HF_CMD_BLDN */
+ BTA_AG_AT_BVRA_EVT, /* BTA_AG_HF_CMD_BVRA */
+ 0, /* BTA_AG_HF_CMD_BRSF */
+ BTA_AG_AT_NREC_EVT, /* BTA_AG_HF_CMD_NREC */
+ BTA_AG_AT_CNUM_EVT, /* BTA_AG_HF_CMD_CNUM */
+ BTA_AG_AT_BTRH_EVT, /* BTA_AG_HF_CMD_BTRH */
+ BTA_AG_AT_CLCC_EVT, /* BTA_AG_HF_CMD_CLCC */
+ BTA_AG_AT_COPS_EVT, /* BTA_AG_HF_CMD_COPS */
+ 0, /* BTA_AG_HF_CMD_CMEE */
+ 0, /* BTA_AG_HF_CMD_BIA */
+ BTA_AG_AT_CBC_EVT, /* BTA_AG_HF_CMD_CBC */
+ 0, /* BTA_AG_HF_CMD_BCC */
+ BTA_AG_AT_BCS_EVT, /* BTA_AG_HF_CMD_BCS */
+ BTA_AG_AT_BAC_EVT /* BTA_AG_HF_CMD_BAC */
+};
+
+/* translation of API result code values to internal values */
+const UINT8 bta_ag_trans_result[] =
+{
+ BTA_AG_RES_VGS, /* BTA_AG_SPK_RES */
+ BTA_AG_RES_VGM, /* BTA_AG_MIC_RES */
+ BTA_AG_RES_BSIR, /* BTA_AG_INBAND_RING_RES */
+ BTA_AG_RES_CIND, /* BTA_AG_CIND_RES */
+ BTA_AG_RES_BINP, /* BTA_AG_BINP_RES */
+ BTA_AG_RES_CIEV, /* BTA_AG_IND_RES */
+ BTA_AG_RES_BVRA, /* BTA_AG_BVRA_RES */
+ BTA_AG_RES_CNUM, /* BTA_AG_CNUM_RES */
+ BTA_AG_RES_BTRH, /* BTA_AG_BTRH_RES */
+ BTA_AG_RES_CLCC, /* BTA_AG_CLCC_RES */
+ BTA_AG_RES_COPS, /* BTA_AG_COPS_RES */
+ 0, /* BTA_AG_IN_CALL_RES */
+ 0, /* BTA_AG_IN_CALL_CONN_RES */
+ BTA_AG_RES_CCWA, /* BTA_AG_CALL_WAIT_RES */
+ 0, /* BTA_AG_OUT_CALL_ORIG_RES */
+ 0, /* BTA_AG_OUT_CALL_ALERT_RES */
+ 0, /* BTA_AG_OUT_CALL_CONN_RES */
+ 0, /* BTA_AG_CALL_CANCEL_RES */
+ 0, /* BTA_AG_END_CALL_RES */
+ 0, /* BTA_AG_IN_CALL_HELD_RES */
+ BTA_AG_RES_UNAT /* BTA_AG_UNAT_RES */
+};
+
+/* callsetup indicator value lookup table */
+const UINT8 bta_ag_callsetup_ind_tbl[] =
+{
+ 0, /* BTA_AG_SPK_RES */
+ 0, /* BTA_AG_MIC_RES */
+ 0, /* BTA_AG_INBAND_RING_RES */
+ 0, /* BTA_AG_CIND_RES */
+ 0, /* BTA_AG_BINP_RES */
+ 0, /* BTA_AG_IND_RES */
+ 0, /* BTA_AG_BVRA_RES */
+ 0, /* BTA_AG_CNUM_RES */
+ 0, /* BTA_AG_BTRH_RES */
+ 0, /* BTA_AG_CLCC_RES */
+ 0, /* BTA_AG_COPS_RES */
+ BTA_AG_CALLSETUP_INCOMING, /* BTA_AG_IN_CALL_RES */
+ BTA_AG_CALLSETUP_NONE, /* BTA_AG_IN_CALL_CONN_RES */
+ BTA_AG_CALLSETUP_INCOMING, /* BTA_AG_CALL_WAIT_RES */
+ BTA_AG_CALLSETUP_OUTGOING, /* BTA_AG_OUT_CALL_ORIG_RES */
+ BTA_AG_CALLSETUP_ALERTING, /* BTA_AG_OUT_CALL_ALERT_RES */
+ BTA_AG_CALLSETUP_NONE, /* BTA_AG_OUT_CALL_CONN_RES */
+ BTA_AG_CALLSETUP_NONE, /* BTA_AG_CALL_CANCEL_RES */
+ BTA_AG_CALLSETUP_NONE, /* BTA_AG_END_CALL_RES */
+ BTA_AG_CALLSETUP_NONE /* BTA_AG_IN_CALL_HELD_RES */
+};
+
+/*******************************************************************************
+**
+** Function bta_ag_send_result
+**
+** Description Send an AT result code.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_send_result(tBTA_AG_SCB *p_scb, UINT8 code, char *p_arg,
+ INT16 int_arg)
+{
+ char buf[BTA_AG_AT_MAX_LEN + 16];
+ char *p = buf;
+ UINT16 len;
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+ memset(buf, NULL, sizeof(buf));
+#endif
+ /* init with \r\n */
+ *p++ = '\r';
+ *p++ = '\n';
+
+ /* copy result code string */
+ BCM_STRCPY_S(p, sizeof(buf), bta_ag_result_tbl[code].p_res);
+#if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
+ if(p_scb->conn_service == BTA_AG_HSP)
+ {
+ /* If HSP then ":"symbol should be changed as "=" for HSP compatibility */
+ switch(code)
+ {
+ case BTA_AG_RES_VGS:
+ case BTA_AG_RES_VGM:
+ if(*(p+COLON_IDX_4_VGSVGM) == ':')
+ {
+ #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("[HSP] ':'symbol is changed as '=' for HSP compatibility");
+ #endif
+ *(p+COLON_IDX_4_VGSVGM) = '=';
+ }
+ break;
+ }
+ }
+#endif
+ p += strlen(bta_ag_result_tbl[code].p_res);
+
+ /* copy argument if any */
+ if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_INT)
+ {
+ p += utl_itoa((UINT16) int_arg, p);
+ }
+ else if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_STR)
+ {
+ BCM_STRCPY_S(p, sizeof(buf), p_arg);
+ p += strlen(p_arg);
+ }
+
+ /* finish with \r\n */
+ *p++ = '\r';
+ *p++ = '\n';
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG1("bta_ag_send_result: %s", buf);
+#endif
+
+ /* send to RFCOMM */
+ PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
+}
+
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function bta_ag_send_multi_result
+**
+** Description Send multiple AT result codes.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_send_multi_result(tBTA_AG_SCB *p_scb, tBTA_AG_MULTI_RESULT_CB *m_res_cb)
+{
+ char buf[BTA_AG_AT_MAX_LEN * BTA_AG_AT_MULTI_LEN + 16];
+ char *p = buf;
+ UINT16 len;
+ UINT8 res_idx = 0;
+
+ if((!m_res_cb) || (m_res_cb->num_result == 0) || (m_res_cb->num_result > BTA_AG_AT_MULTI_LEN))
+ {
+ APPL_TRACE_DEBUG0("m_res_cb is NULL or num_result is out of range.");
+ return;
+ }
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+ memset(buf, NULL, sizeof(buf));
+#endif
+
+ while(res_idx < m_res_cb->num_result)
+ {
+ /* init with \r\n */
+ *p++ = '\r';
+ *p++ = '\n';
+
+ /* copy result code string */
+ BCM_STRCPY_S(p, sizeof(buf), bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
+ p += strlen(bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
+
+ /* copy argument if any */
+ if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_INT)
+ {
+ p += utl_itoa((UINT16) m_res_cb->res_cb[res_idx].int_arg, p);
+ }
+ else if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_STR)
+ {
+ BCM_STRCPY_S(p, sizeof(buf), m_res_cb->res_cb[res_idx].p_arg);
+ p += strlen(m_res_cb->res_cb[res_idx].p_arg);
+ }
+
+ /* finish with \r\n */
+ *p++ = '\r';
+ *p++ = '\n';
+
+ res_idx++;
+ }
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG1("send_result: %s", buf);
+#endif
+
+ /* send to RFCOMM */
+ PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ag_send_ok
+**
+** Description Send an OK result code.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_send_ok(tBTA_AG_SCB *p_scb)
+{
+ bta_ag_send_result(p_scb, BTA_AG_RES_OK, NULL, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_send_error
+**
+** Description Send an ERROR result code.
+** errcode - used to send verbose errocode
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_send_error(tBTA_AG_SCB *p_scb, INT16 errcode)
+{
+ /* If HFP and extended audio gateway error codes are enabled */
+ if (p_scb->conn_service == BTA_AG_HFP && p_scb->cmee_enabled)
+ bta_ag_send_result(p_scb, BTA_AG_RES_CMEE, NULL, errcode);
+ else
+ bta_ag_send_result(p_scb, BTA_AG_RES_ERROR, NULL, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_send_ind
+**
+** Description Send an indicator CIEV result code.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_send_ind(tBTA_AG_SCB *p_scb, UINT16 id, UINT16 value, BOOLEAN on_demand)
+{
+ char str[12];
+ char *p = str;
+
+ /* If the indicator is masked out, just return */
+ /* Mandatory indicators can not be masked out. */
+ if ((p_scb->bia_masked_out & ((UINT32)1 << id)) &&
+ ((id != BTA_AG_IND_CALL) && (id != BTA_AG_IND_CALLSETUP) && (id != BTA_AG_IND_CALLHELD)))
+ return;
+
+ /* Ensure we do not send duplicate indicators if not requested by app */
+ /* If it was requested by app, transmit CIEV even if it is duplicate. */
+ if (id == BTA_AG_IND_CALL)
+ {
+ if ((value == p_scb->call_ind) && (on_demand == FALSE))
+ return;
+
+ p_scb->call_ind = (UINT8)value;
+ }
+
+ if ((id == BTA_AG_IND_CALLSETUP) && (on_demand == FALSE))
+ {
+ if (value == p_scb->callsetup_ind)
+ return;
+
+ p_scb->callsetup_ind = (UINT8)value;
+ }
+
+ if ((id == BTA_AG_IND_SERVICE) && (on_demand == FALSE))
+ {
+ if (value == p_scb->service_ind)
+ return;
+
+ p_scb->service_ind = (UINT8)value;
+ }
+ if ((id == BTA_AG_IND_SIGNAL) && (on_demand == FALSE))
+ {
+ if (value == p_scb->signal_ind)
+ return;
+
+ p_scb->signal_ind = (UINT8)value;
+ }
+ if ((id == BTA_AG_IND_ROAM) && (on_demand == FALSE))
+ {
+ if (value == p_scb->roam_ind)
+ return;
+
+ p_scb->roam_ind = (UINT8)value;
+ }
+ if ((id == BTA_AG_IND_BATTCHG) && (on_demand == FALSE))
+ {
+ if (value == p_scb->battchg_ind)
+ return;
+
+ p_scb->battchg_ind = (UINT8)value;
+ }
+
+ if ((id == BTA_AG_IND_CALLHELD) && (on_demand == FALSE))
+ {
+ /* call swap could result in sending callheld=1 multiple times */
+ if ((value != 1) && (value == p_scb->callheld_ind))
+ return;
+
+ p_scb->callheld_ind = (UINT8)value;
+ }
+
+ if (p_scb->cmer_enabled)
+ {
+ p += utl_itoa(id, p);
+ *p++ = ',';
+ utl_itoa(value, p);
+ bta_ag_send_result(p_scb, BTA_AG_RES_CIEV, str, 0);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_parse_cmer
+**
+** Description Parse AT+CMER parameter string.
+**
+**
+** Returns TRUE if parsed ok, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_ag_parse_cmer(char *p_s, BOOLEAN *p_enabled)
+{
+ INT16 n[4] = {-1, -1, -1, -1};
+ int i;
+ char *p;
+
+ for (i = 0; i < 4; i++)
+ {
+ /* skip to comma delimiter */
+ for (p = p_s; *p != ',' && *p != 0; p++);
+
+ /* get integer value */
+ *p = 0;
+ n[i] = utl_str2int(p_s);
+ p_s = p + 1;
+ if (p_s == 0)
+ {
+ break;
+ }
+ }
+
+ /* process values */
+ if (n[0] < 0 || n[3] < 0)
+ {
+ return FALSE;
+ }
+
+ if ((n[0] == 3) && ((n[3] == 1) || (n[3] == 0)))
+ {
+ *p_enabled = (BOOLEAN) n[3];
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_parse_chld
+**
+** Description Parse AT+CHLD parameter string.
+**
+**
+** Returns Returns idx (1-7), or 0 if ECC not enabled or idx doesn't exist
+**
+*******************************************************************************/
+static UINT8 bta_ag_parse_chld(tBTA_AG_SCB *p_scb, char *p_s)
+{
+ UINT8 retval = 0;
+ INT16 idx = -1;
+
+ if (p_s[1] != 0)
+ {
+ /* p_idxstr++; point to beginning of call number */
+ idx = utl_str2int(&p_s[1]);
+ if (idx != -1 && idx < 255)
+ retval = (UINT8)idx;
+ }
+
+ return (retval);
+}
+
+#if (BTM_WBS_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function bta_ag_parse_bac
+**
+** Description Parse AT+BAC parameter string.
+**
+** Returns Returns bitmap of supported codecs.
+**
+*******************************************************************************/
+static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB *p_scb, char *p_s)
+{
+ tBTA_AG_PEER_CODEC retval = BTA_AG_CODEC_NONE;
+ UINT16 uuid_codec;
+ BOOLEAN cont = FALSE; /* Continue processing */
+ char *p;
+
+ while(p_s)
+ {
+ /* skip to comma delimiter */
+ for(p = p_s; *p != ',' && *p != 0; p++);
+
+ /* get integre value */
+ if (*p != 0)
+ {
+ *p = 0;
+ cont = TRUE;
+ }
+ else
+ cont = FALSE;
+
+ uuid_codec = utl_str2int(p_s);
+ switch(uuid_codec)
+ {
+ case UUID_CODEC_CVSD: retval |= BTA_AG_CODEC_CVSD; break;
+ case UUID_CODEC_MSBC: retval |= BTA_AG_CODEC_MSBC; break;
+ default:
+ APPL_TRACE_ERROR1("Unknown Codec UUID(%d) received", uuid_codec);
+ return BTA_AG_CODEC_NONE;
+ }
+
+ if (cont)
+ p_s = p + 1;
+ else
+ break;
+ }
+
+ return (retval);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ag_process_unat_res
+**
+** Description Process the unat response data and remove extra carriage return
+** and line feed
+**
+**
+** Returns void
+**
+*******************************************************************************/
+
+static void bta_ag_process_unat_res(char *unat_result)
+{
+ UINT8 str_leng;
+ UINT8 i = 0;
+ UINT8 j = 0;
+ UINT8 pairs_of_nl_cr;
+ char trim_data[BTA_AG_AT_MAX_LEN];
+
+
+
+ str_leng = strlen(unat_result);
+
+ /* If no extra CR and LF, just return */
+ if(str_leng < 4)
+ return;
+
+ /* Remove the carriage return and left feed */
+ while(unat_result[0] =='\r' && unat_result[1] =='\n'
+ && unat_result[str_leng-2] =='\r' && unat_result[str_leng-1] =='\n')
+ {
+ pairs_of_nl_cr = 1;
+ for (i=0;i<(str_leng-4*pairs_of_nl_cr);i++)
+ {
+ trim_data[j++] = unat_result[i+pairs_of_nl_cr*2];
+ }
+ /* Add EOF */
+ trim_data[j] = '\0';
+ str_leng = str_leng - 4;
+ BCM_STRNCPY_S(unat_result, BTA_AG_AT_MAX_LEN+1, trim_data,str_leng+1);
+ i=0;
+ j=0;
+
+ if(str_leng <4)
+ return;
+
+
+ }
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ag_inband_enabled
+**
+** Description Determine whether in-band ring can be used.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_ag_inband_enabled(tBTA_AG_SCB *p_scb)
+{
+ /* if feature is enabled and no other scbs connected */
+ if (p_scb->inband_enabled && !bta_ag_other_scb_open(p_scb))
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_send_call_inds
+**
+** Description Send call and callsetup indicators.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result)
+{
+ UINT8 call = p_scb->call_ind;
+ UINT8 callsetup;
+
+ /* set new call and callsetup values based on BTA_AgResult */
+ callsetup = bta_ag_callsetup_ind_tbl[result];
+
+ if (result == BTA_AG_END_CALL_RES)
+ {
+ call = BTA_AG_CALL_INACTIVE;
+ }
+ else if (result == BTA_AG_IN_CALL_CONN_RES || result == BTA_AG_OUT_CALL_CONN_RES
+ || result == BTA_AG_IN_CALL_HELD_RES)
+ {
+ call = BTA_AG_CALL_ACTIVE;
+ }
+ else
+ {
+ call = p_scb->call_ind;
+ }
+
+ /* Send indicator function tracks if the values have actually changed */
+ bta_ag_send_ind(p_scb, BTA_AG_IND_CALL, call, FALSE);
+ bta_ag_send_ind(p_scb, BTA_AG_IND_CALLSETUP, callsetup, FALSE);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_at_hsp_cback
+**
+** Description AT command processing callback for HSP.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+ char *p_arg, INT16 int_arg)
+{
+ tBTA_AG_VAL val;
+
+ APPL_TRACE_DEBUG4("AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
+ int_arg, p_arg);
+
+ /* send OK */
+ bta_ag_send_ok(p_scb);
+
+ val.hdr.handle = bta_ag_scb_to_idx(p_scb);
+ val.hdr.app_id = p_scb->app_id;
+ val.num = (UINT16) int_arg;
+ BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
+ val.str[BTA_AG_AT_MAX_LEN] = 0;
+
+ /* call callback with event */
+ (*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_at_hfp_cback
+**
+** Description AT command processing callback for HFP.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+ char *p_arg, INT16 int_arg)
+{
+ tBTA_AG_VAL val;
+ tBTA_AG_EVT event;
+ tBTA_AG_SCB *ag_scb;
+ UINT32 i, ind_id;
+ UINT32 bia_masked_out;
+#if (BTM_WBS_INCLUDED == TRUE )
+ tBTA_AG_PEER_CODEC codec_type, codec_sent;
+#endif
+
+ APPL_TRACE_DEBUG4("HFP AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
+ int_arg, p_arg);
+
+ val.hdr.handle = bta_ag_scb_to_idx(p_scb);
+ val.hdr.app_id = p_scb->app_id;
+ val.num = int_arg;
+ BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
+ val.str[BTA_AG_AT_MAX_LEN] = 0;
+
+ event = bta_ag_hfp_cb_evt[cmd];
+
+ switch (cmd)
+ {
+ case BTA_AG_HF_CMD_A:
+ case BTA_AG_HF_CMD_VGS:
+ case BTA_AG_HF_CMD_VGM:
+ case BTA_AG_HF_CMD_CHUP:
+ case BTA_AG_HF_CMD_CBC:
+ /* send OK */
+ bta_ag_send_ok(p_scb);
+ break;
+
+ case BTA_AG_HF_CMD_BLDN:
+ /* Do not send OK, App will send error or OK depending on
+ ** last dial number enabled or not */
+ break;
+
+ case BTA_AG_HF_CMD_D:
+ /* Do not send OK for Dial cmds
+ ** Let application decide whether to send OK or ERROR*/
+
+ /* if mem dial cmd, make sure string contains only digits */
+ if(p_arg[0] == '>')
+ {
+ if(!utl_isintstr(p_arg+1))
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
+ }
+ }
+ else if (p_arg[0] == 'V') /* ATDV : Dial VoIP Call */
+ {
+ /* We do not check string. Code will be added later if needed. */
+ if(!((p_scb->peer_features & BTA_AG_PEER_FEAT_VOIP) && (p_scb->features & BTA_AG_FEAT_VOIP)))
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ }
+ }
+ /* If dial cmd, make sure string contains only dial digits
+ ** Dial digits are 0-9, A-C, *, #, + */
+ else
+ {
+ if(!utl_isdialstr(p_arg))
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
+ }
+ }
+ break;
+
+ case BTA_AG_HF_CMD_CCWA:
+ /* store setting */
+ p_scb->ccwa_enabled = (BOOLEAN) int_arg;
+
+ /* send OK */
+ bta_ag_send_ok(p_scb);
+ break;
+
+ case BTA_AG_HF_CMD_CHLD:
+ if (arg_type == BTA_AG_AT_TEST)
+ {
+ /* don't call callback */
+ event = 0;
+
+ /* send CHLD string */
+ /* Form string based on supported 1.5 feature */
+ if ((p_scb->peer_version >= HFP_VERSION_1_5) &&
+ (p_scb->features & BTA_AG_FEAT_ECC) &&
+ (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))
+ bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val_ecc, 0);
+ else
+ bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val, 0);
+
+ /* send OK */
+ bta_ag_send_ok(p_scb);
+
+ /* if service level conn. not already open, now it's open */
+ bta_ag_svc_conn_open(p_scb, NULL);
+
+ }
+ else
+ {
+ val.idx = bta_ag_parse_chld(p_scb, val.str);
+
+ if(val.idx && !((p_scb->features & BTA_AG_FEAT_ECC) && (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC)))
+ {
+ /* we do not support ECC, but HF is sending us a CHLD with call index*/
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+
+ }
+ else
+ {
+
+ /* If it is swap between calls, set call held indicator to 3(out of valid 0-2)
+ ** Application will set it back to 1
+ ** callheld indicator will be sent across to the peer. */
+ if(val.str[0] == '2')
+ {
+ for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
+ {
+ if (ag_scb->in_use)
+ {
+ if((ag_scb->call_ind == BTA_AG_CALL_ACTIVE)
+ && (ag_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
+ ag_scb->callheld_ind = BTA_AG_CALLHELD_NOACTIVE + 1;
+ }
+ }
+ }
+ }
+
+ /* Do not send OK. Let app decide after parsing the val str */
+ /* bta_ag_send_ok(p_scb); */
+ }
+ break;
+
+ case BTA_AG_HF_CMD_CIND:
+ if (arg_type == BTA_AG_AT_TEST)
+ {
+ /* don't call callback */
+ event = 0;
+
+ /* send CIND string, send OK */
+ bta_ag_send_result(p_scb, BTA_AG_RES_CIND, p_bta_ag_cfg->cind_info, 0);
+ bta_ag_send_ok(p_scb);
+ }
+ break;
+
+ case BTA_AG_HF_CMD_CLIP:
+ /* store setting, send OK */
+ p_scb->clip_enabled = (BOOLEAN) int_arg;
+ bta_ag_send_ok(p_scb);
+ break;
+
+ case BTA_AG_HF_CMD_CMER:
+ /* if parsed ok store setting, send OK */
+ if (bta_ag_parse_cmer(p_arg, &p_scb->cmer_enabled))
+ {
+ bta_ag_send_ok(p_scb);
+
+ /* if service level conn. not already open and our features and
+ ** peer features do not have 3-way, service level conn. now open
+ */
+ if (!p_scb->svc_conn &&
+ !((p_scb->features & BTA_AG_FEAT_3WAY) && (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY)))
+ {
+ bta_ag_svc_conn_open(p_scb, NULL);
+ }
+ }
+ else
+ {
+ bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
+ }
+ break;
+
+ case BTA_AG_HF_CMD_VTS:
+ /* check argument */
+ if (strlen(p_arg) == 1)
+ {
+ bta_ag_send_ok(p_scb);
+ }
+ else
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
+ }
+ break;
+
+ case BTA_AG_HF_CMD_BINP:
+ /* if feature not set don't call callback, send ERROR */
+ if (!(p_scb->features & BTA_AG_FEAT_VTAG))
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ }
+ break;
+
+ case BTA_AG_HF_CMD_BVRA:
+ /* if feature not supported don't call callback, send ERROR. App will send OK */
+ if (!(p_scb->features & BTA_AG_FEAT_VREC))
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ }
+ break;
+
+ case BTA_AG_HF_CMD_BRSF:
+ /* store peer features */
+ p_scb->peer_features = (UINT16) int_arg;
+
+ /* send BRSF, send OK */
+ bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL,
+ (INT16) (p_scb->features & BTA_AG_BSRF_FEAT_SPEC));
+ bta_ag_send_ok(p_scb);
+ break;
+
+ case BTA_AG_HF_CMD_NREC:
+ /* if feature send OK, else don't call callback, send ERROR */
+ if (p_scb->features & BTA_AG_FEAT_ECNR)
+ {
+ bta_ag_send_ok(p_scb);
+ }
+ else
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ }
+ break;
+
+ case BTA_AG_HF_CMD_BTRH:
+ /* if feature send BTRH, send OK:, else don't call callback, send ERROR */
+ if (p_scb->features & BTA_AG_FEAT_BTRH)
+ {
+ /* If set command; send response and notify app */
+ if (arg_type == BTA_AG_AT_SET)
+ {
+ for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
+ {
+ if (ag_scb->in_use)
+ {
+ bta_ag_send_result(ag_scb, BTA_AG_RES_BTRH, NULL, int_arg);
+ }
+ }
+ bta_ag_send_ok(p_scb);
+ }
+ else /* Read Command */
+ {
+ val.num = BTA_AG_BTRH_READ;
+ }
+ }
+ else
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ }
+ break;
+
+ case BTA_AG_HF_CMD_COPS:
+ if (arg_type == BTA_AG_AT_SET)
+ {
+ /* don't call callback */
+ event = 0;
+
+ /* send OK */
+ bta_ag_send_ok(p_scb);
+ }
+ break;
+
+ case BTA_AG_HF_CMD_CMEE:
+ if (p_scb->features & BTA_AG_FEAT_EXTERR)
+ {
+ /* store setting */
+ p_scb->cmee_enabled = (BOOLEAN) int_arg;
+
+ /* send OK */
+ bta_ag_send_ok(p_scb);
+ }
+ else
+ {
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ }
+ /* don't call callback */
+ event = 0;
+ break;
+
+ case BTA_AG_HF_CMD_BIA:
+ /* don't call callback */
+ event = 0;
+
+ bia_masked_out = p_scb->bia_masked_out;
+
+ /* Parse the indicator mask */
+ for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20); i++, ind_id++)
+ {
+ if (val.str[i] == ',')
+ continue;
+
+ if (val.str[i] == '0')
+ bia_masked_out |= ((UINT32)1 << ind_id);
+ else if (val.str[i] == '1')
+ bia_masked_out &= ~((UINT32)1 << ind_id);
+ else
+ break;
+
+ i++;
+ if ( (val.str[i] != 0) && (val.str[i] != ',') )
+ break;
+ }
+ if (val.str[i] == 0)
+ {
+ p_scb->bia_masked_out = bia_masked_out;
+ bta_ag_send_ok (p_scb);
+ }
+ else
+ bta_ag_send_error (p_scb, BTA_AG_ERR_INVALID_INDEX);
+ break;
+
+ case BTA_AG_HF_CMD_CNUM:
+ break;
+ case BTA_AG_HF_CMD_CLCC:
+ if(!(p_scb->features & BTA_AG_FEAT_ECS))
+ {
+ event = 0;
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ }
+ break;
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ case BTA_AG_HF_CMD_BAC:
+ bta_ag_send_ok(p_scb);
+
+ /* store available codecs from the peer */
+ if((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) && (p_scb->features & BTA_AG_FEAT_CODEC))
+ {
+ p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg);
+ p_scb->codec_updated = TRUE;
+
+ if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC)
+ {
+ p_scb->sco_codec = UUID_CODEC_MSBC;
+ APPL_TRACE_DEBUG0("Received AT+BAC, updating sco codec to MSBC");
+ }
+ else
+ {
+ p_scb->sco_codec = UUID_CODEC_CVSD;
+ APPL_TRACE_DEBUG0("Received AT+BAC, updating sco codec to CVSD");
+ }
+
+ /* Received BAC while in codec negotiation. */
+ if ((bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST) && (bta_ag_cb.sco.p_curr_scb == p_scb))
+ {
+ bta_ag_codec_negotiate (p_scb);
+ }
+ }
+ else
+ {
+ p_scb->peer_codecs = BTA_AG_CODEC_NONE;
+ APPL_TRACE_ERROR0("Unexpected CMD:AT+BAC, Codec Negotiation is not supported");
+ }
+ break;
+
+ case BTA_AG_HF_CMD_BCS:
+ /* stop cn timer */
+ bta_sys_stop_timer(&p_scb->cn_timer);
+
+ switch(int_arg)
+ {
+ case UUID_CODEC_CVSD: codec_type = BTA_AG_CODEC_CVSD; break;
+ case UUID_CODEC_MSBC: codec_type = BTA_AG_CODEC_MSBC; break;
+ default:
+ APPL_TRACE_ERROR1("Unknown codec_uuid %d", int_arg);
+ codec_type = 0xFFFF;
+ break;
+ }
+
+ if (p_scb->codec_fallback)
+ codec_sent = BTA_AG_CODEC_CVSD;
+ else
+ codec_sent = p_scb->sco_codec;
+
+ if(codec_type == codec_sent)
+ bta_ag_sco_codec_nego(p_scb, TRUE);
+ else
+ bta_ag_sco_codec_nego(p_scb, FALSE);
+
+ bta_ag_send_ok(p_scb);
+ break;
+
+ case BTA_AG_HF_CMD_BCC:
+ bta_ag_send_ok(p_scb);
+ bta_ag_sco_open(p_scb, NULL);
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ /* call callback */
+ if (event != 0)
+ {
+ (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &val);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_at_err_cback
+**
+** Description AT command parser error callback.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg)
+{
+ tBTA_AG_VAL val;
+
+ if(unknown && (!strlen(p_arg)))
+ {
+ APPL_TRACE_DEBUG0("Empty AT cmd string received");
+ bta_ag_send_ok(p_scb);
+ return;
+ }
+
+ /* if unknown AT command and configured to pass these to app */
+ if (unknown && (p_scb->features & BTA_AG_FEAT_UNAT))
+ {
+ val.hdr.handle = bta_ag_scb_to_idx(p_scb);
+ val.hdr.app_id = p_scb->app_id;
+ val.num = 0;
+ BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
+ val.str[BTA_AG_AT_MAX_LEN] = 0;
+ (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG *) &val);
+ }
+ else
+ {
+ bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_hsp_result
+**
+** Description Handle API result for HSP connections.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
+{
+ UINT8 code = bta_ag_trans_result[p_result->result];
+
+ APPL_TRACE_DEBUG1("bta_ag_hsp_result : res = %d", p_result->result);
+
+ switch(p_result->result)
+ {
+ case BTA_AG_SPK_RES:
+ case BTA_AG_MIC_RES:
+ bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+ break;
+
+ case BTA_AG_IN_CALL_RES:
+ /* tell sys to stop av if any */
+ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ /* if sco already opened or no inband ring send ring now */
+ if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
+ (p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ /* else open sco, send ring after sco opened */
+ else
+ {
+ /* HSPv1.2: AG shall not send RING if using in-band ring tone. */
+ if (p_scb->hsp_version >= HSP_VERSION_1_2)
+ p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+ else
+ p_scb->post_sco = BTA_AG_POST_SCO_RING;
+
+ bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ break;
+
+ case BTA_AG_IN_CALL_CONN_RES:
+ case BTA_AG_OUT_CALL_ORIG_RES:
+ /* if incoming call connected stop ring timer */
+ if (p_result->result == BTA_AG_IN_CALL_CONN_RES)
+ {
+ bta_sys_stop_timer(&p_scb->act_timer);
+ }
+
+ if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ /* if audio connected to this scb open sco */
+ if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
+ {
+ bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ /* else if no audio at call close sco */
+ else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
+ {
+ bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ }
+ break;
+
+ case BTA_AG_END_CALL_RES:
+ /* stop ring timer */
+ bta_sys_stop_timer(&p_scb->act_timer);
+
+ /* close sco */
+ if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ else
+ {
+ /* if av got suspended by this call, let it resume. */
+ bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+ }
+ break;
+
+ case BTA_AG_INBAND_RING_RES:
+ p_scb->inband_enabled = p_result->data.state;
+ APPL_TRACE_DEBUG1("inband_enabled set to %d", p_scb->inband_enabled);
+ break;
+
+ case BTA_AG_UNAT_RES:
+ if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
+ {
+ if (p_result->data.str[0] != 0)
+ {
+ bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ }
+
+ if (p_result->data.ok_flag == BTA_AG_OK_DONE)
+ bta_ag_send_ok(p_scb);
+ }
+ else
+ {
+ bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
+ }
+ break;
+
+ default:
+ /* ignore all others */
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_hfp_result
+**
+** Description Handle API result for HFP connections.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
+{
+ UINT8 code = bta_ag_trans_result[p_result->result];
+
+ APPL_TRACE_DEBUG1("bta_ag_hfp_result : res = %d", p_result->result);
+
+ switch(p_result->result)
+ {
+ case BTA_AG_SPK_RES:
+ case BTA_AG_MIC_RES:
+ bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+ break;
+
+ case BTA_AG_IN_CALL_RES:
+ /* tell sys to stop av if any */
+ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ /* store caller id string.
+ * append type info at the end.
+ * make sure a valid type info is passed.
+ * otherwise add 129 as default type */
+ if ((p_result->data.num < BTA_AG_CLIP_TYPE_MIN) || (p_result->data.num > BTA_AG_CLIP_TYPE_MAX))
+ {
+ if (p_result->data.num != BTA_AG_CLIP_TYPE_VOIP)
+ p_result->data.num = BTA_AG_CLIP_TYPE_DEFAULT;
+ }
+
+ APPL_TRACE_DEBUG1("CLIP type :%d", p_result->data.num);
+ p_scb->clip[0] = 0;
+ if (p_result->data.str[0] != 0)
+ sprintf(p_scb->clip,"%s,%d", p_result->data.str, p_result->data.num);
+
+ /* send callsetup indicator */
+ if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)
+ {
+ /* Need to sent 2 callsetup IND's(Call End and Incoming call) after SCO close. */
+ p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL;
+ }
+ else
+ {
+ bta_ag_send_call_inds(p_scb, p_result->result);
+
+ /* if sco already opened or no inband ring send ring now */
+ if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
+ (p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ /* else open sco, send ring after sco opened */
+ else
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_RING;
+ bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ }
+ break;
+
+ case BTA_AG_IN_CALL_CONN_RES:
+ /* stop ring timer */
+ bta_sys_stop_timer(&p_scb->act_timer);
+
+ /* if sco not opened and we need to open it, open sco first
+ ** then send indicators
+ */
+ if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+ !bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_CALL_CONN;
+ bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ /* else if sco open and we need to close it, close sco first
+ ** then send indicators
+ */
+ else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE &&
+ bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_CALL_CONN;
+ bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ /* else send indicators now */
+ else
+ {
+ bta_ag_send_call_inds(p_scb, p_result->result);
+ }
+ break;
+
+ case BTA_AG_IN_CALL_HELD_RES:
+ /* stop ring timer */
+ bta_sys_stop_timer(&p_scb->act_timer);
+
+ bta_ag_send_call_inds(p_scb, p_result->result);
+
+ break;
+
+ case BTA_AG_OUT_CALL_ORIG_RES:
+ /* if sco open and we need to close it, close sco first
+ ** then send indicators; else send indicators now
+ */
+ if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE &&
+ bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_CALL_ORIG;
+ bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ else
+ {
+ bta_ag_send_call_inds(p_scb, p_result->result);
+ if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+ !(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ }
+ break;
+
+ case BTA_AG_OUT_CALL_ALERT_RES:
+ /* send indicators */
+ bta_ag_send_call_inds(p_scb, p_result->result);
+ if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+ !(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ break;
+
+ case BTA_AG_OUT_CALL_CONN_RES:
+ /* send indicators */
+ bta_ag_send_call_inds(p_scb, p_result->result);
+
+ /* open or close sco */
+ if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
+ {
+ bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
+ {
+ bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ }
+ break;
+
+ case BTA_AG_CALL_CANCEL_RES:
+ /* send indicators */
+ bta_ag_send_call_inds(p_scb, p_result->result);
+ break;
+
+ case BTA_AG_END_CALL_RES:
+ /* stop ring timer */
+ bta_sys_stop_timer(&p_scb->act_timer);
+
+ /* if sco open, close sco then send indicator values */
+ if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+ {
+ p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
+ bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+ }
+ else if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END_INCALL)
+ {
+ /* sco closing for outgoing call because of incoming call */
+ /* Send only callsetup end indicator after sco close */
+ p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
+ }
+ else
+ {
+ bta_ag_send_call_inds(p_scb, p_result->result);
+
+ /* if av got suspended by this call, let it resume. */
+ bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+ }
+ break;
+
+ case BTA_AG_INBAND_RING_RES:
+ p_scb->inband_enabled = p_result->data.state;
+ APPL_TRACE_DEBUG1("inband_enabled set to %d", p_scb->inband_enabled);
+ bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
+ break;
+
+ case BTA_AG_CIND_RES:
+ /* store local values */
+ p_scb->call_ind = p_result->data.str[0] - '0';
+ p_scb->callsetup_ind = p_result->data.str[2] - '0';
+ p_scb->service_ind = p_result->data.str[4] - '0';
+ p_scb->signal_ind = p_result->data.str[6] - '0';
+ p_scb->roam_ind = p_result->data.str[8] - '0';
+ p_scb->battchg_ind = p_result->data.str[10] - '0';
+ APPL_TRACE_DEBUG2("cind call:%d callsetup:%d", p_scb->call_ind, p_scb->callsetup_ind);
+
+ bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ bta_ag_send_ok(p_scb);
+ break;
+
+ case BTA_AG_BINP_RES:
+ case BTA_AG_CNUM_RES:
+ case BTA_AG_CLCC_RES:
+ case BTA_AG_COPS_RES:
+ if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
+ {
+ if (p_result->data.str[0] != 0)
+ {
+ bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ }
+
+ if (p_result->data.ok_flag == BTA_AG_OK_DONE)
+ bta_ag_send_ok(p_scb);
+ }
+ else
+ {
+ bta_ag_send_error(p_scb, p_result->data.errcode);
+ }
+ break;
+
+
+ case BTA_AG_UNAT_RES:
+ if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
+ {
+ if (p_result->data.str[0] != 0)
+ {
+ bta_ag_process_unat_res(p_result->data.str);
+ APPL_TRACE_DEBUG1("BTA_AG_RES :%s",p_result->data.str);
+ bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ }
+
+ if (p_result->data.ok_flag == BTA_AG_OK_DONE)
+ bta_ag_send_ok(p_scb);
+ }
+ else
+ {
+ bta_ag_send_error(p_scb, p_result->data.errcode);
+ }
+ break;
+
+ case BTA_AG_CALL_WAIT_RES:
+ if (p_scb->ccwa_enabled)
+ {
+ bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+ }
+ bta_ag_send_call_inds(p_scb, p_result->result);
+ break;
+
+ case BTA_AG_IND_RES:
+ bta_ag_send_ind(p_scb, p_result->data.ind.id, p_result->data.ind.value, FALSE);
+ break;
+
+ case BTA_AG_BVRA_RES:
+ bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
+ break;
+
+ case BTA_AG_BTRH_RES:
+ if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
+ {
+ /* Don't respond to read if not in response & hold state */
+ if (p_result->data.num != BTA_AG_BTRH_NO_RESP)
+ {
+ bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+ }
+
+ /* In case of a response to a read request we need to send OK */
+ if (p_result->data.ok_flag == BTA_AG_OK_DONE)
+ bta_ag_send_ok(p_scb);
+ }
+ else
+ {
+ bta_ag_send_error(p_scb, p_result->data.errcode);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ag_result
+**
+** Description Handle API result.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ if (p_scb->conn_service == BTA_AG_HSP)
+ {
+ bta_ag_hsp_result(p_scb, &p_data->api_result);
+ }
+ else
+ {
+ bta_ag_hfp_result(p_scb, &p_data->api_result);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_setcodec
+**
+** Description Handle API SetCodec
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+#if (BTM_WBS_INCLUDED == TRUE )
+ tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec;
+
+ /* Check if the requested codec type is valid */
+ if((codec_type != BTA_AG_CODEC_NONE) &&
+ (codec_type != BTA_AG_CODEC_CVSD) &&
+ (codec_type != BTA_AG_CODEC_MSBC))
+ {
+ APPL_TRACE_ERROR1("bta_ag_setcodec error: unsupported codec type %d", codec_type);
+ return;
+ }
+
+ if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) || (codec_type == BTA_AG_CODEC_CVSD))
+ {
+ p_scb->sco_codec = codec_type;
+ p_scb->codec_updated = TRUE;
+ APPL_TRACE_DEBUG1("bta_ag_setcodec: Updated codec type %d", codec_type);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ag_setcodec error: unsupported codec type %d", codec_type);
+ }
+#endif
+}
+
+
+#if (BTM_WBS_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function bta_ag_send_bcs
+**
+** Description Send +BCS AT command to peer.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ UINT16 codec_uuid;
+
+ if (p_scb->codec_fallback)
+ {
+ codec_uuid = UUID_CODEC_CVSD;
+ }
+ else
+ {
+ switch(p_scb->sco_codec)
+ {
+ case BTA_AG_CODEC_NONE: codec_uuid = UUID_CODEC_CVSD; break;
+ case BTA_AG_CODEC_CVSD: codec_uuid = UUID_CODEC_CVSD; break;
+ case BTA_AG_CODEC_MSBC: codec_uuid = UUID_CODEC_MSBC; break;
+ default:
+ APPL_TRACE_ERROR1("bta_ag_send_bcs: unknown codec %d, use CVSD", p_scb->sco_codec);
+ codec_uuid = UUID_CODEC_CVSD;
+ break;
+ }
+ }
+
+ /* send +BCS */
+ bta_ag_send_result(p_scb, BTA_AG_RES_BCS, NULL, codec_uuid);
+
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ag_send_ring
+**
+** Description Send RING result code to peer.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+ tBTA_AG_MULTI_RESULT_CB m_res_cb;
+
+ if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
+ {
+ memset(&m_res_cb, NULL, sizeof(tBTA_AG_MULTI_RESULT_CB));
+
+ m_res_cb.num_result = 2;
+ AT_SET_RES_CB(m_res_cb.res_cb[0], BTA_AG_RES_RING, NULL, 0)
+ AT_SET_RES_CB(m_res_cb.res_cb[1], BTA_AG_RES_CLIP, p_scb->clip, 0)
+
+ bta_ag_send_multi_result(p_scb, &m_res_cb);
+ }
+ else
+ {
+ /* send RING ONLY */
+ bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
+ }
+#else
+ /* send RING */
+ bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
+
+ /* if HFP and clip enabled and clip data send CLIP */
+ if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
+ {
+ bta_ag_send_result(p_scb, BTA_AG_RES_CLIP, p_scb->clip, 0);
+ }
+#endif
+
+ /* restart ring timer */
+ bta_sys_start_timer(&p_scb->act_timer, BTA_AG_RING_TOUT_EVT, BTA_AG_RING_TOUT);
+}
+
+
diff --git a/bta/ag/bta_ag_int.h b/bta/ag/bta_ag_int.h
new file mode 100644
index 0000000..b0d1b1d
--- /dev/null
+++ b/bta/ag/bta_ag_int.h
@@ -0,0 +1,423 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private interface file for the BTA audio gateway.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_INT_H
+#define BTA_AG_INT_H
+
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_ag_api.h"
+#include "bta_ag_at.h"
+
+/* Send RING & CLIP in one AT cmd */
+#ifndef BTA_AG_MULTI_RESULT_INCLUDED
+#define BTA_AG_MULTI_RESULT_INCLUDED FALSE
+#endif
+
+/* Replace : in VGS and VGM for HSP */
+#ifndef BTA_HSP_RESULT_REPLACE_COLON
+#define BTA_HSP_RESULT_REPLACE_COLON TRUE
+#endif
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+#define HFP_VERSION_1_1 0x0101
+#define HFP_VERSION_1_5 0x0105
+#define HFP_VERSION_1_6 0x0106
+
+#define HSP_VERSION_1_0 0x0100
+#define HSP_VERSION_1_2 0x0102
+
+/* Number of SCBs (AG service instances that can be registered) */
+#ifndef BTA_AG_NUM_SCB
+#define BTA_AG_NUM_SCB 2
+#endif
+
+/* Timer to wait for retry in case of collision */
+#ifndef BTA_AG_COLLISION_TIMER
+#define BTA_AG_COLLISION_TIMER 2000
+#endif
+
+/* RFCOMM MTU SIZE */
+#define BTA_AG_MTU 256
+
+/* Internal profile indexes */
+#define BTA_AG_HSP 0 /* index for HSP */
+#define BTA_AG_HFP 1 /* index for HFP */
+#define BTA_AG_NUM_IDX 2 /* number of profile indexes */
+
+/* profile role for connection */
+#define BTA_AG_ACP 0 /* accepted connection */
+#define BTA_AG_INT 1 /* initiating connection */
+
+/* feature mask that matches spec */
+#define BTA_AG_BSRF_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \
+ BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \
+ BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT | \
+ BTA_AG_FEAT_ECS | BTA_AG_FEAT_ECC | \
+ BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \
+ BTA_AG_FEAT_VOIP)
+
+#define BTA_AG_SDP_FEAT_SPEC (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR | \
+ BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND | \
+ BTA_AG_FEAT_VTAG)
+
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_AG_API_REGISTER_EVT = BTA_SYS_EVT_START(BTA_ID_AG),
+ BTA_AG_API_DEREGISTER_EVT,
+ BTA_AG_API_OPEN_EVT,
+ BTA_AG_API_CLOSE_EVT,
+ BTA_AG_API_AUDIO_OPEN_EVT,
+ BTA_AG_API_AUDIO_CLOSE_EVT,
+ BTA_AG_API_RESULT_EVT,
+ BTA_AG_API_SETCODEC_EVT,
+ BTA_AG_RFC_OPEN_EVT,
+ BTA_AG_RFC_CLOSE_EVT,
+ BTA_AG_RFC_SRV_CLOSE_EVT,
+ BTA_AG_RFC_DATA_EVT,
+ BTA_AG_SCO_OPEN_EVT,
+ BTA_AG_SCO_CLOSE_EVT,
+ BTA_AG_DISC_ACP_RES_EVT,
+ BTA_AG_DISC_INT_RES_EVT,
+ BTA_AG_DISC_OK_EVT,
+ BTA_AG_DISC_FAIL_EVT,
+ BTA_AG_CI_RX_WRITE_EVT,
+ BTA_AG_RING_TOUT_EVT,
+ BTA_AG_SVC_TOUT_EVT,
+ BTA_AG_CI_SCO_DATA_EVT,
+ BTA_AG_CI_SLC_READY_EVT,
+ BTA_AG_MAX_EVT,
+
+ /* these events are handled outside of the state machine */
+ BTA_AG_API_ENABLE_EVT,
+ BTA_AG_API_DISABLE_EVT
+};
+
+/* Actions to perform after a SCO event */
+enum
+{
+ BTA_AG_POST_SCO_NONE, /* no action */
+ BTA_AG_POST_SCO_CLOSE_RFC, /* close RFCOMM channel after SCO closes */
+ BTA_AG_POST_SCO_RING, /* send RING result code after SCO opens */
+ BTA_AG_POST_SCO_CALL_CONN, /* send call indicators after SCO opens/closes */
+ BTA_AG_POST_SCO_CALL_ORIG, /* send call indicators after SCO closes */
+ BTA_AG_POST_SCO_CALL_END, /* send call indicators after SCO closes */
+ BTA_AG_POST_SCO_CALL_END_INCALL /* send call indicators for end call & incoming call after SCO closes */
+};
+
+/* sco states */
+enum
+{
+ BTA_AG_SCO_SHUTDOWN_ST, /* no sco listening, all sco connections closed */
+ BTA_AG_SCO_LISTEN_ST, /* sco listening */
+#if (BTM_WBS_INCLUDED == TRUE )
+ BTA_AG_SCO_CODEC_ST, /* sco codec negotiation */
+#endif
+ BTA_AG_SCO_OPENING_ST, /* sco connection opening */
+ BTA_AG_SCO_OPEN_CL_ST, /* opening sco connection being closed */
+ BTA_AG_SCO_OPEN_XFER_ST, /* opening sco connection being transferred */
+ BTA_AG_SCO_OPEN_ST, /* sco open */
+ BTA_AG_SCO_CLOSING_ST, /* sco closing */
+ BTA_AG_SCO_CLOSE_OP_ST, /* closing sco being opened */
+ BTA_AG_SCO_CLOSE_XFER_ST, /* closing sco being transferred */
+ BTA_AG_SCO_SHUTTING_ST /* sco shutting down */
+};
+
+/*****************************************************************************
+** Data types
+*****************************************************************************/
+
+/* data type for BTA_AG_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_AG_PARSE_MODE parse_mode;
+ tBTA_AG_CBACK *p_cback;
+} tBTA_AG_API_ENABLE;
+
+/* data type for BTA_AG_API_REGISTER_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char p_name[2][BTA_SERVICE_NAME_LEN+1];
+ tBTA_SERVICE_MASK services;
+ tBTA_SEC sec_mask;
+ tBTA_AG_FEAT features;
+ UINT8 app_id;
+} tBTA_AG_API_REGISTER;
+
+/* data type for BTA_AG_API_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_SERVICE_MASK services;
+ tBTA_SEC sec_mask;
+} tBTA_AG_API_OPEN;
+
+/* data type for BTA_AG_API_RESULT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_AG_RES result;
+ tBTA_AG_RES_DATA data;
+} tBTA_AG_API_RESULT;
+
+/* data type for BTA_AG_API_SETCODEC_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_AG_PEER_CODEC codec;
+} tBTA_AG_API_SETCODEC;
+
+/* data type for BTA_AG_DISC_RESULT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 status;
+} tBTA_AG_DISC_RESULT;
+
+/* data type for RFCOMM events */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 port_handle;
+} tBTA_AG_RFC;
+
+/* data type for BTA_AG_CI_RX_WRITE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+// char p_data[BTA_AG_MTU+1];
+} tBTA_AG_CI_RX_WRITE;
+
+/* union of all event datatypes */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_AG_API_ENABLE api_enable;
+ tBTA_AG_API_REGISTER api_register;
+ tBTA_AG_API_OPEN api_open;
+ tBTA_AG_API_RESULT api_result;
+#if (BTM_WBS_INCLUDED == TRUE )
+ tBTA_AG_API_SETCODEC api_setcodec;
+#endif
+ tBTA_AG_DISC_RESULT disc_result;
+ tBTA_AG_RFC rfc;
+ tBTA_AG_CI_RX_WRITE ci_rx_write;
+} tBTA_AG_DATA;
+
+/* type for each profile */
+typedef struct
+{
+ UINT32 sdp_handle;
+ UINT8 scn;
+} tBTA_AG_PROFILE;
+
+/* type for each service control block */
+typedef struct
+{
+ char clip[BTA_AG_AT_MAX_LEN+1]; /* number string used for CLIP */
+ UINT16 serv_handle[BTA_AG_NUM_IDX]; /* RFCOMM server handles */
+ tBTA_AG_AT_CB at_cb; /* AT command interpreter */
+ TIMER_LIST_ENT act_timer; /* ring timer */
+ BD_ADDR peer_addr; /* peer bd address */
+ tSDP_DISCOVERY_DB *p_disc_db; /* pointer to discovery database */
+ tBTA_SERVICE_MASK reg_services; /* services specified in register API */
+ tBTA_SERVICE_MASK open_services; /* services specified in open API */
+ UINT16 conn_handle; /* RFCOMM handle of connected service */
+ tBTA_SEC serv_sec_mask; /* server security mask */
+ tBTA_SEC cli_sec_mask; /* client security mask */
+ tBTA_AG_FEAT features; /* features registered by application */
+ tBTA_AG_PEER_FEAT peer_features; /* peer device features */
+ UINT16 peer_version; /* profile version of peer device */
+ UINT16 hsp_version; /* HSP profile version */
+#if (BTM_WBS_INCLUDED == TRUE )
+ tBTA_AG_PEER_CODEC peer_codecs; /* codecs for eSCO supported by the peer */
+ tBTA_AG_PEER_CODEC sco_codec; /* codec to be used for eSCO connection */
+ tBTA_AG_PEER_CODEC inuse_codec; /* codec being used for the current SCO connection */
+ BOOLEAN codec_updated; /* set to TRUE whenever the app updates codec type */
+ BOOLEAN codec_fallback; /* If sco nego fails for mSBC, fallback to CVSD */
+ TIMER_LIST_ENT cn_timer; /* codec negotiation timer */
+#endif
+ UINT16 sco_idx; /* SCO handle */
+ BOOLEAN in_use; /* scb in use */
+ BOOLEAN dealloc; /* TRUE if service shutting down */
+ BOOLEAN clip_enabled; /* set to TRUE if HF enables CLIP reporting */
+ BOOLEAN ccwa_enabled; /* set to TRUE if HF enables CCWA reporting */
+ BOOLEAN cmer_enabled; /* set to TRUE if HF enables CMER reporting */
+ BOOLEAN cmee_enabled; /* set to TRUE if HF enables CME ERROR reporting */
+ BOOLEAN inband_enabled; /* set to TRUE if inband ring enabled */
+ BOOLEAN svc_conn; /* set to TRUE when service level connection up */
+ TIMER_LIST_ENT colli_timer; /* Collision timer */
+ BOOLEAN colli_tmr_on; /* TRUE if collision timer is active */
+ UINT8 state; /* state machine state */
+ UINT8 conn_service; /* connected service */
+ UINT8 peer_scn; /* peer scn */
+ UINT8 app_id; /* application id */
+ UINT8 role; /* initiator/acceptor role */
+ UINT8 post_sco; /* action to perform after sco event */
+ UINT8 call_ind; /* CIEV call indicator value */
+ UINT8 callsetup_ind; /* CIEV callsetup indicator value */
+ UINT8 service_ind; /* CIEV service indicator value */
+ UINT8 signal_ind; /* CIEV signal indicator value */
+ UINT8 roam_ind; /* CIEV roam indicator value */
+ UINT8 battchg_ind; /* CIEV battery charge indicator value */
+ UINT8 callheld_ind; /* CIEV call held indicator value */
+ BOOLEAN retry_with_sco_only; /* indicator to try with SCO only when eSCO fails */
+ UINT32 bia_masked_out; /* indicators HF does not want us to send */
+} tBTA_AG_SCB;
+
+/* type for sco data */
+typedef struct
+{
+ tBTM_ESCO_CONN_REQ_EVT_DATA conn_data; /* SCO data for pending conn request */
+ tBTA_AG_SCB *p_curr_scb; /* SCB associated with SCO connection */
+ tBTA_AG_SCB *p_xfer_scb; /* SCB associated with SCO transfer */
+ UINT16 cur_idx; /* SCO handle */
+ UINT8 state; /* SCO state variable */
+ BOOLEAN param_updated; /* if params were updated to non-default */
+ tBTM_ESCO_PARAMS params; /* ESCO parameters */
+} tBTA_AG_SCO_CB;
+
+
+/* type for AG control block */
+typedef struct
+{
+ tBTA_AG_SCB scb[BTA_AG_NUM_SCB]; /* service control blocks */
+ tBTA_AG_PROFILE profile[BTA_AG_NUM_IDX]; /* profile-specific data */
+ tBTA_AG_SCO_CB sco; /* SCO data */
+ tBTA_AG_CBACK *p_cback; /* application callback */
+ tBTA_AG_PARSE_MODE parse_mode; /* parse/pass-through mode */
+} tBTA_AG_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* constant lookup tables */
+extern const UINT16 bta_ag_uuid[BTA_AG_NUM_IDX];
+extern const UINT8 bta_ag_sec_id[BTA_AG_NUM_IDX];
+extern const tBTA_AG_AT_CMD *bta_ag_at_tbl[BTA_AG_NUM_IDX];
+
+/* control block declaration */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_AG_CB bta_ag_cb;
+#else
+extern tBTA_AG_CB *bta_ag_cb_ptr;
+#define bta_ag_cb (*bta_ag_cb_ptr)
+#endif
+
+/* config struct */
+extern tBTA_AG_CFG *p_bta_ag_cfg;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+/* main functions */
+extern void bta_ag_scb_dealloc(tBTA_AG_SCB *p_scb);
+extern UINT16 bta_ag_scb_to_idx(tBTA_AG_SCB *p_scb);
+extern tBTA_AG_SCB *bta_ag_scb_by_idx(UINT16 idx);
+extern UINT8 bta_ag_service_to_idx(tBTA_SERVICE_MASK services);
+extern UINT16 bta_ag_idx_by_bdaddr(BD_ADDR peer_addr);
+extern BOOLEAN bta_ag_other_scb_open(tBTA_AG_SCB *p_curr_scb);
+extern tBTA_AG_SCB *bta_ag_get_other_idle_scb (tBTA_AG_SCB *p_curr_scb);
+extern void bta_ag_sm_execute(tBTA_AG_SCB *p_scb, UINT16 event, tBTA_AG_DATA *p_data);
+extern BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg);
+extern void bta_ag_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id,
+ UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_ag_resume_open (tBTA_AG_SCB *p_scb);
+
+/* SDP functions */
+extern BOOLEAN bta_ag_add_record(UINT16 service_uuid, char *p_service_name, UINT8 scn,
+ tBTA_AG_FEAT features, UINT32 sdp_handle);
+extern void bta_ag_create_records(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_del_records(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern BOOLEAN bta_ag_sdp_find_attr(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service);
+extern void bta_ag_do_disc(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service);
+extern void bta_ag_free_db(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+
+/* RFCOMM functions */
+extern void bta_ag_start_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services);
+extern void bta_ag_close_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services);
+extern BOOLEAN bta_ag_is_server_closed (tBTA_AG_SCB *p_scb);
+extern void bta_ag_rfc_do_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_do_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+
+/* SCO functions */
+extern BOOLEAN bta_ag_sco_is_open(tBTA_AG_SCB *p_scb);
+extern BOOLEAN bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb);
+extern void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data);
+
+/* AT command functions */
+extern void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+ char *p_arg, INT16 int_arg);
+extern void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+ char *p_arg, INT16 int_arg);
+extern void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg);
+extern BOOLEAN bta_ag_inband_enabled(tBTA_AG_SCB *p_scb);
+extern void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result);
+
+/* Action functions */
+extern void bta_ag_register(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_deregister(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_start_dereg(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_disc_int_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_disc_acp_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_disc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_open_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+#if (BTM_WBS_INCLUDED == TRUE )
+extern void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result);
+extern void bta_ag_codec_negotiate (tBTA_AG_SCB *p_scb);
+#endif
+extern void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_post_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_post_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+#if (BTM_WBS_INCLUDED == TRUE )
+extern void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+#endif
+extern void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param);
+extern void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+#endif /* BTA_AG_INT_H */
diff --git a/bta/ag/bta_ag_main.c b/bta/ag/bta_ag_main.c
new file mode 100644
index 0000000..9b28067
--- /dev/null
+++ b/bta/ag/bta_ag_main.c
@@ -0,0 +1,1012 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the main implementation file for the BTA audio gateway.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_co.h"
+#include "bta_ag_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+#ifndef BTA_AG_DEBUG
+#define BTA_AG_DEBUG FALSE
+#endif
+
+#if BTA_AG_DEBUG == TRUE
+static char *bta_ag_evt_str(UINT16 event, tBTA_AG_RES result);
+static char *bta_ag_state_str(UINT8 state);
+#endif
+
+/* state machine states */
+enum
+{
+ BTA_AG_INIT_ST,
+ BTA_AG_OPENING_ST,
+ BTA_AG_OPEN_ST,
+ BTA_AG_CLOSING_ST
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_AG_REGISTER,
+ BTA_AG_DEREGISTER,
+ BTA_AG_START_OPEN,
+ BTA_AG_RFC_DO_OPEN,
+ BTA_AG_RFC_DO_CLOSE,
+ BTA_AG_START_DEREG,
+ BTA_AG_START_CLOSE,
+ BTA_AG_RFC_OPEN,
+ BTA_AG_OPEN_FAIL,
+ BTA_AG_RFC_ACP_OPEN,
+ BTA_AG_RFC_CLOSE,
+ BTA_AG_RFC_FAIL,
+ BTA_AG_RFC_DATA,
+ BTA_AG_DISC_INT_RES,
+ BTA_AG_DISC_FAIL,
+ BTA_AG_DISC_ACP_RES,
+ BTA_AG_FREE_DB,
+ BTA_AG_SCO_CONN_OPEN,
+ BTA_AG_SCO_CONN_CLOSE,
+ BTA_AG_SCO_LISTEN,
+ BTA_AG_SCO_OPEN,
+ BTA_AG_SCO_CLOSE,
+ BTA_AG_SCO_SHUTDOWN,
+ BTA_AG_POST_SCO_OPEN,
+ BTA_AG_POST_SCO_CLOSE,
+ BTA_AG_SVC_CONN_OPEN,
+ BTA_AG_RESULT,
+ BTA_AG_SETCODEC,
+ BTA_AG_SEND_RING,
+ BTA_AG_CI_SCO_DATA,
+ BTA_AG_CI_RX_DATA,
+ BTA_AG_RCVD_SLC_READY,
+ BTA_AG_NUM_ACTIONS
+};
+
+#define BTA_AG_IGNORE BTA_AG_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tBTA_AG_ACTION)(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+
+/* action functions */
+const tBTA_AG_ACTION bta_ag_action[] =
+{
+ bta_ag_register,
+ bta_ag_deregister,
+ bta_ag_start_open,
+ bta_ag_rfc_do_open,
+ bta_ag_rfc_do_close,
+ bta_ag_start_dereg,
+ bta_ag_start_close,
+ bta_ag_rfc_open,
+ bta_ag_open_fail,
+ bta_ag_rfc_acp_open,
+ bta_ag_rfc_close,
+ bta_ag_rfc_fail,
+ bta_ag_rfc_data,
+ bta_ag_disc_int_res,
+ bta_ag_disc_fail,
+ bta_ag_disc_acp_res,
+ bta_ag_free_db,
+ bta_ag_sco_conn_open,
+ bta_ag_sco_conn_close,
+ bta_ag_sco_listen,
+ bta_ag_sco_open,
+ bta_ag_sco_close,
+ bta_ag_sco_shutdown,
+ bta_ag_post_sco_open,
+ bta_ag_post_sco_close,
+ bta_ag_svc_conn_open,
+ bta_ag_result,
+ bta_ag_setcodec,
+ bta_ag_send_ring,
+ bta_ag_ci_sco_data,
+ bta_ag_ci_rx_data,
+ bta_ag_rcvd_slc_ready
+};
+
+/* state table information */
+#define BTA_AG_ACTIONS 2 /* number of actions */
+#define BTA_AG_NEXT_STATE 2 /* position of next state */
+#define BTA_AG_NUM_COLS 3 /* number of columns in state tables */
+
+/* state table for init state */
+const UINT8 bta_ag_st_init[][BTA_AG_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* API_REGISTER_EVT */ {BTA_AG_REGISTER, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* API_DEREGISTER_EVT */ {BTA_AG_DEREGISTER, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* API_OPEN_EVT */ {BTA_AG_START_OPEN, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* API_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* API_AUDIO_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* API_AUDIO_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* API_RESULT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* API_SETCODEC_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* RFC_OPEN_EVT */ {BTA_AG_RFC_ACP_OPEN, BTA_AG_SCO_LISTEN, BTA_AG_OPEN_ST},
+/* RFC_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* RFC_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* SCO_OPEN_EVT */ {BTA_AG_SCO_CONN_OPEN, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* SCO_CLOSE_EVT */ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* DISC_ACP_RES_EVT */ {BTA_AG_FREE_DB, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* DISC_INT_RES_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* CI_RX_WRITE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* CI_SCO_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* CI_SLC_READY_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}
+};
+
+/* state table for opening state */
+const UINT8 bta_ag_st_opening[][BTA_AG_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* API_REGISTER_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* API_DEREGISTER_EVT */ {BTA_AG_RFC_DO_CLOSE, BTA_AG_START_DEREG, BTA_AG_CLOSING_ST},
+/* API_OPEN_EVT */ {BTA_AG_OPEN_FAIL, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* API_CLOSE_EVT */ {BTA_AG_RFC_DO_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_AUDIO_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* API_AUDIO_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* API_RESULT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* API_SETCODEC_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* RFC_OPEN_EVT */ {BTA_AG_RFC_OPEN, BTA_AG_SCO_LISTEN, BTA_AG_OPEN_ST},
+/* RFC_CLOSE_EVT */ {BTA_AG_RFC_FAIL, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* RFC_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* SCO_OPEN_EVT */ {BTA_AG_SCO_CONN_OPEN, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* SCO_CLOSE_EVT */ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* DISC_ACP_RES_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* DISC_INT_RES_EVT */ {BTA_AG_DISC_INT_RES, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* DISC_OK_EVT */ {BTA_AG_RFC_DO_OPEN, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* DISC_FAIL_EVT */ {BTA_AG_DISC_FAIL, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* CI_RX_WRITE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* CI_SCO_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+/* CI_SLC_READY_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}
+};
+
+/* state table for open state */
+const UINT8 bta_ag_st_open[][BTA_AG_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* API_REGISTER_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* API_DEREGISTER_EVT */ {BTA_AG_START_CLOSE, BTA_AG_START_DEREG, BTA_AG_CLOSING_ST},
+/* API_OPEN_EVT */ {BTA_AG_OPEN_FAIL, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* API_CLOSE_EVT */ {BTA_AG_START_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_AUDIO_OPEN_EVT */ {BTA_AG_SCO_OPEN, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* API_AUDIO_CLOSE_EVT */ {BTA_AG_SCO_CLOSE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* API_RESULT_EVT */ {BTA_AG_RESULT, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* API_SETCODEC_EVT */ {BTA_AG_SETCODEC, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* RFC_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* RFC_CLOSE_EVT */ {BTA_AG_RFC_CLOSE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* RFC_DATA_EVT */ {BTA_AG_RFC_DATA, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* SCO_OPEN_EVT */ {BTA_AG_SCO_CONN_OPEN, BTA_AG_POST_SCO_OPEN, BTA_AG_OPEN_ST},
+/* SCO_CLOSE_EVT */ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_POST_SCO_CLOSE, BTA_AG_OPEN_ST},
+/* DISC_ACP_RES_EVT */ {BTA_AG_DISC_ACP_RES, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* DISC_INT_RES_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* CI_RX_WRITE_EVT */ {BTA_AG_CI_RX_DATA, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* RING_TOUT_EVT */ {BTA_AG_SEND_RING, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* SVC_TOUT_EVT */ {BTA_AG_START_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* CI_SCO_DATA_EVT */ {BTA_AG_CI_SCO_DATA, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
+/* CI_SLC_READY_EVT */ {BTA_AG_RCVD_SLC_READY, BTA_AG_IGNORE, BTA_AG_OPEN_ST}
+};
+
+/* state table for closing state */
+const UINT8 bta_ag_st_closing[][BTA_AG_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* API_REGISTER_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_DEREGISTER_EVT */ {BTA_AG_START_DEREG, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_OPEN_EVT */ {BTA_AG_OPEN_FAIL, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_AUDIO_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_AUDIO_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_RESULT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* API_SETCODEC_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* RFC_OPEN_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* RFC_CLOSE_EVT */ {BTA_AG_RFC_CLOSE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* RFC_SRV_CLOSE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* RFC_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* SCO_OPEN_EVT */ {BTA_AG_SCO_CONN_OPEN, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* SCO_CLOSE_EVT */ {BTA_AG_SCO_CONN_CLOSE, BTA_AG_POST_SCO_CLOSE, BTA_AG_CLOSING_ST},
+/* DISC_ACP_RES_EVT */ {BTA_AG_FREE_DB, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* DISC_INT_RES_EVT */ {BTA_AG_FREE_DB, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+/* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* CI_RX_WRITE_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* CI_SCO_DATA_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+/* CI_SLC_READY_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_AG_ST_TBL)[BTA_AG_NUM_COLS];
+
+/* state table */
+const tBTA_AG_ST_TBL bta_ag_st_tbl[] =
+{
+ bta_ag_st_init,
+ bta_ag_st_opening,
+ bta_ag_st_open,
+ bta_ag_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* AG control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_AG_CB bta_ag_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ag_timer_cback
+**
+** Description AG timer callback.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_timer_cback(void *p)
+{
+ BT_HDR *p_buf;
+ TIMER_LIST_ENT *p_tle = (TIMER_LIST_ENT *) p;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = p_tle->event;
+ p_buf->layer_specific = bta_ag_scb_to_idx((tBTA_AG_SCB *) p_tle->param);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_scb_alloc
+**
+** Description Allocate an AG service control block.
+**
+**
+** Returns pointer to the scb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+static tBTA_AG_SCB *bta_ag_scb_alloc(void)
+{
+ tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0];
+ int i;
+
+ for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
+ {
+ if (!p_scb->in_use)
+ {
+ /* initialize variables */
+ p_scb->in_use = TRUE;
+ p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+
+ /* set up timers */
+ p_scb->act_timer.param = (UINT32) p_scb;
+ p_scb->act_timer.p_cback = bta_ag_timer_cback;
+
+ APPL_TRACE_DEBUG1("bta_ag_scb_alloc %d", bta_ag_scb_to_idx(p_scb));
+ break;
+ }
+ }
+
+ if (i == BTA_AG_NUM_SCB)
+ {
+ /* out of scbs */
+ p_scb = NULL;
+ APPL_TRACE_WARNING0("Out of ag scbs");
+ }
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_scb_dealloc
+**
+** Description Deallocate a service control block.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_scb_dealloc(tBTA_AG_SCB *p_scb)
+{
+ UINT8 idx;
+ BOOLEAN allocated = FALSE;
+
+ APPL_TRACE_DEBUG1("bta_ag_scb_dealloc %d", bta_ag_scb_to_idx(p_scb));
+
+ /* stop timers */
+ bta_sys_stop_timer(&p_scb->act_timer);
+#if (BTM_WBS_INCLUDED == TRUE)
+ bta_sys_stop_timer(&p_scb->cn_timer);
+#endif
+
+ /* initialize control block */
+ memset(p_scb, 0, sizeof(tBTA_AG_SCB));
+ p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+
+ /* If all scbs are deallocated, callback with disable event */
+ if (!bta_sys_is_register (BTA_ID_AG))
+ {
+ for (idx = 0; idx < BTA_AG_NUM_SCB; idx++)
+ {
+ if (bta_ag_cb.scb[idx].in_use)
+ {
+ allocated = TRUE;
+ break;
+ }
+ }
+
+ if (!allocated)
+ {
+ (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL);
+ }
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_scb_to_idx
+**
+** Description Given a pointer to an scb, return its index.
+**
+**
+** Returns Index of scb.
+**
+*******************************************************************************/
+UINT16 bta_ag_scb_to_idx(tBTA_AG_SCB *p_scb)
+{
+ /* use array arithmetic to determine index */
+ return ((UINT16) (p_scb - bta_ag_cb.scb)) + 1;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_scb_by_idx
+**
+** Description Given an scb index return pointer to scb.
+**
+**
+** Returns Pointer to scb or NULL if not allocated.
+**
+*******************************************************************************/
+tBTA_AG_SCB *bta_ag_scb_by_idx(UINT16 idx)
+{
+ tBTA_AG_SCB *p_scb;
+
+ /* verify index */
+ if (idx > 0 && idx <= BTA_AG_NUM_SCB)
+ {
+ p_scb = &bta_ag_cb.scb[idx - 1];
+ if (!p_scb->in_use)
+ {
+ p_scb = NULL;
+ APPL_TRACE_WARNING1("ag scb idx %d not allocated", idx);
+ }
+ }
+ else
+ {
+ p_scb = NULL;
+ APPL_TRACE_DEBUG1("ag scb idx %d out of range", idx);
+ }
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_service_to_idx
+**
+** Description Given a BTA service mask convert to profile index.
+**
+**
+** Returns Profile ndex of scb.
+**
+*******************************************************************************/
+UINT8 bta_ag_service_to_idx(tBTA_SERVICE_MASK services)
+{
+ if (services & BTA_HFP_SERVICE_MASK)
+ {
+ return BTA_AG_HFP;
+ }
+ else
+ {
+ return BTA_AG_HSP;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_idx_by_bdaddr
+**
+** Description Find SCB associated with peer BD address.
+**
+**
+** Returns Index of SCB or zero if none found.
+**
+*******************************************************************************/
+UINT16 bta_ag_idx_by_bdaddr(BD_ADDR peer_addr)
+{
+ tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0];
+ UINT16 i;
+
+ if (peer_addr != NULL)
+ {
+ for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
+ {
+ if (p_scb->in_use && !bdcmp(peer_addr, p_scb->peer_addr))
+ {
+ return (i + 1);
+ }
+ }
+ }
+
+ /* no scb found */
+ APPL_TRACE_WARNING0("No ag scb for peer addr");
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_other_scb_open
+**
+** Description Check whether any other scb is in open state.
+**
+**
+** Returns TRUE if another scb is in open state, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_ag_other_scb_open(tBTA_AG_SCB *p_curr_scb)
+{
+ tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0];
+ int i;
+
+ for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
+ {
+ if (p_scb->in_use && p_scb != p_curr_scb && p_scb->state == BTA_AG_OPEN_ST)
+ {
+ return TRUE;
+ }
+ }
+
+ /* no other scb found */
+ APPL_TRACE_DEBUG0("No other ag scb open");
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_get_other_idle_scb
+**
+** Description Return other scb if it is in INIT st.
+**
+**
+** Returns Pointer to other scb if INIT st, NULL otherwise.
+**
+*******************************************************************************/
+tBTA_AG_SCB *bta_ag_get_other_idle_scb (tBTA_AG_SCB *p_curr_scb)
+{
+ tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0];
+ UINT8 xx;
+
+ for (xx = 0; xx < BTA_AG_NUM_SCB; xx++, p_scb++)
+ {
+ if (p_scb->in_use && (p_scb != p_curr_scb) && (p_scb->state == BTA_AG_INIT_ST))
+ {
+ return p_scb;
+ }
+ }
+
+ /* no other scb found */
+ APPL_TRACE_DEBUG0("bta_ag_get_other_idle_scb: No idle AG scb");
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_colli_timer_cback
+**
+** Description AG connection collision timer callback
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_colli_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+ tBTA_AG_SCB *p_scb;
+
+ APPL_TRACE_DEBUG0 ("bta_ag_colli_timer_cback");
+
+ if (p_tle)
+ {
+ p_scb = (tBTA_AG_SCB *)p_tle->param;
+
+ if (p_scb)
+ {
+ p_scb->colli_tmr_on = FALSE;
+
+ /* If the peer haven't opened AG connection */
+ /* we will restart opening process. */
+ bta_ag_resume_open (p_scb);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_collision_cback
+**
+** Description Get notified about collision.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id,
+ UINT8 app_id, BD_ADDR peer_addr)
+{
+ UINT16 handle;
+ tBTA_AG_SCB *p_scb;
+
+ /* Check if we have opening scb for the peer device. */
+ handle = bta_ag_idx_by_bdaddr (peer_addr);
+ p_scb = bta_ag_scb_by_idx (handle);
+
+ if (p_scb && (p_scb->state == BTA_AG_OPENING_ST))
+ {
+ if (id == BTA_ID_SYS) /* ACL collision */
+ {
+ APPL_TRACE_WARNING0 ("AG found collision (ACL) ...");
+ }
+ else if (id == BTA_ID_AG) /* RFCOMM collision */
+ {
+ APPL_TRACE_WARNING0 ("AG found collision (RFCOMM) ...");
+ }
+ else
+ {
+ APPL_TRACE_WARNING0 ("AG found collision (\?\?\?) ...");
+ }
+
+ p_scb->state = BTA_AG_INIT_ST;
+
+ /* Cancel SDP if it had been started. */
+ if(p_scb->p_disc_db)
+ {
+ (void)SDP_CancelServiceSearch (p_scb->p_disc_db);
+ bta_ag_free_db(p_scb, NULL);
+ }
+
+ /* reopen registered servers */
+ /* Collision may be detected before or after we close servers. */
+ if (bta_ag_is_server_closed (p_scb))
+ bta_ag_start_servers(p_scb, p_scb->reg_services);
+
+ /* Start timer to han */
+ p_scb->colli_timer.p_cback = (TIMER_CBACK*)&bta_ag_colli_timer_cback;
+ p_scb->colli_timer.param = (INT32)p_scb;
+ bta_sys_start_timer(&p_scb->colli_timer, 0, BTA_AG_COLLISION_TIMER);
+ p_scb->colli_tmr_on = TRUE;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_resume_open
+**
+** Description Resume opening process.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_resume_open (tBTA_AG_SCB *p_scb)
+{
+ if (p_scb)
+ {
+ APPL_TRACE_DEBUG1 ("bta_ag_resume_open, Handle(%d)", bta_ag_scb_to_idx(p_scb));
+
+ /* resume opening process. */
+ if (p_scb->state == BTA_AG_INIT_ST)
+ {
+ p_scb->state = BTA_AG_OPENING_ST;
+ bta_ag_start_open (p_scb, NULL);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0 ("bta_ag_resume_open, Null p_scb");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_api_enable
+**
+** Description Handle an API enable event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_api_enable(tBTA_AG_DATA *p_data)
+{
+ /* initialize control block */
+ memset(&bta_ag_cb, 0, sizeof(tBTA_AG_CB));
+
+ /* store callback function */
+ bta_ag_cb.p_cback = p_data->api_enable.p_cback;
+ bta_ag_cb.parse_mode = p_data->api_enable.parse_mode;
+
+ /* call init call-out */
+ bta_ag_co_init();
+
+ bta_sys_collision_register (BTA_ID_AG, bta_ag_collision_cback);
+
+ /* call callback with enable event */
+ (*bta_ag_cb.p_cback)(BTA_AG_ENABLE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_api_disable
+**
+** Description Handle an API disable event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_api_disable(tBTA_AG_DATA *p_data)
+{
+ /* deregister all scbs in use */
+ tBTA_AG_SCB *p_scb = &bta_ag_cb.scb[0];
+ BOOLEAN do_dereg = FALSE;
+ int i;
+
+ if (!bta_sys_is_register (BTA_ID_AG))
+ {
+ APPL_TRACE_ERROR0("BTA AG is already disabled, ignoring ...");
+ return;
+ }
+
+ /* De-register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_deregister(BTA_ID_AG);
+ GKI_sched_unlock();
+
+ for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
+ {
+ if (p_scb->in_use)
+ {
+ bta_ag_sm_execute(p_scb, BTA_AG_API_DEREGISTER_EVT, p_data);
+ do_dereg = TRUE;
+ }
+ }
+
+ if (!do_dereg)
+ {
+ /* Done, send callback evt to app */
+ (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL);
+ }
+
+ bta_sys_collision_register (BTA_ID_AG, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_api_register
+**
+** Description Handle an API event registers a new service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_api_register(tBTA_AG_DATA *p_data)
+{
+ tBTA_AG_SCB *p_scb;
+ tBTA_AG_REGISTER reg;
+
+ /* allocate an scb */
+ if ((p_scb = bta_ag_scb_alloc()) != NULL)
+ {
+ bta_ag_sm_execute(p_scb, p_data->hdr.event, p_data);
+ }
+ else
+ {
+ reg.status = BTA_AG_FAIL_RESOURCES;
+ (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG *) ®);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_api_result
+**
+** Description Handle an API result event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_api_result(tBTA_AG_DATA *p_data)
+{
+ tBTA_AG_SCB *p_scb;
+ int i;
+
+ if (p_data->hdr.layer_specific != BTA_AG_HANDLE_ALL)
+ {
+ if ((p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific)) != NULL)
+ {
+ bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
+ }
+ }
+ else
+ {
+ for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, p_scb++)
+ {
+ if (p_scb->in_use)
+ {
+ bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sm_execute
+**
+** Description State machine event handling function for AG
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sm_execute(tBTA_AG_SCB *p_scb, UINT16 event, tBTA_AG_DATA *p_data)
+{
+ tBTA_AG_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+#if BTA_AG_DEBUG == TRUE
+ UINT16 in_event = event;
+ UINT8 in_state = p_scb->state;
+
+ /* Ignore displaying of AT results when not connected (Ignored in state machine) */
+ if (in_event != BTA_AG_API_RESULT_EVT || p_scb->state == BTA_AG_OPEN_ST)
+ {
+ APPL_TRACE_EVENT5("AG evt (hdl 0x%04x): State %d (%s), Event 0x%04x (%s)",
+ bta_ag_scb_to_idx(p_scb),
+ p_scb->state, bta_ag_state_str(p_scb->state),
+ event, bta_ag_evt_str(event, p_data->api_result.result));
+ }
+#else
+ APPL_TRACE_EVENT3("AG evt (hdl 0x%04x): State %d, Event 0x%04x",
+ bta_ag_scb_to_idx(p_scb), p_scb->state, event);
+#endif
+
+ event &= 0x00FF;
+ if (event >= (BTA_AG_MAX_EVT & 0x00FF))
+ {
+ APPL_TRACE_ERROR0("AG evt out of range, ignoring...");
+ return;
+ }
+
+ /* look up the state table for the current state */
+ state_table = bta_ag_st_tbl[p_scb->state];
+
+ /* set next state */
+ p_scb->state = state_table[event][BTA_AG_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_AG_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_AG_IGNORE)
+ {
+ (*bta_ag_action[action])(p_scb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+#if BTA_AG_DEBUG == TRUE
+ if (p_scb->state != in_state)
+ {
+ APPL_TRACE_EVENT3("BTA AG State Change: [%s] -> [%s] after Event [%s]",
+ bta_ag_state_str(in_state),
+ bta_ag_state_str(p_scb->state),
+ bta_ag_evt_str(in_event, p_data->api_result.result));
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_hdl_event
+**
+** Description Data gateway main event handling function.
+**
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg)
+{
+ tBTA_AG_SCB *p_scb;
+
+ switch (p_msg->event)
+ {
+ /* handle enable event */
+ case BTA_AG_API_ENABLE_EVT:
+ bta_ag_api_enable((tBTA_AG_DATA *) p_msg);
+ break;
+
+ /* handle disable event */
+ case BTA_AG_API_DISABLE_EVT:
+ bta_ag_api_disable((tBTA_AG_DATA *) p_msg);
+ break;
+
+ /* handle register event */
+ case BTA_AG_API_REGISTER_EVT:
+ bta_ag_api_register((tBTA_AG_DATA *) p_msg);
+ break;
+
+ /* handle result event */
+ case BTA_AG_API_RESULT_EVT:
+ bta_ag_api_result((tBTA_AG_DATA *) p_msg);
+ break;
+
+ /* all others reference scb by handle */
+ default:
+ if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL)
+ {
+ bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA *) p_msg);
+ }
+ break;
+ }
+ return TRUE;
+}
+
+#if BTA_AG_DEBUG == TRUE
+static char *bta_ag_evt_str(UINT16 event, tBTA_AG_RES result)
+{
+ switch (event)
+ {
+ case BTA_AG_API_REGISTER_EVT:
+ return "Register Request";
+ case BTA_AG_API_DEREGISTER_EVT:
+ return "Deregister Request";
+ case BTA_AG_API_OPEN_EVT:
+ return "Open SLC Request";
+ case BTA_AG_API_CLOSE_EVT:
+ return "Close SLC Request";
+ case BTA_AG_API_AUDIO_OPEN_EVT:
+ return "Open Audio Request";
+ case BTA_AG_API_AUDIO_CLOSE_EVT:
+ return "Close Audio Request";
+ case BTA_AG_API_RESULT_EVT:
+ switch (result)
+ {
+ case BTA_AG_SPK_RES: return ("AT Result BTA_AG_SPK_RES");
+ case BTA_AG_MIC_RES: return ("AT Result BTA_AG_MIC_RES");
+ case BTA_AG_INBAND_RING_RES: return ("AT Result BTA_AG_INBAND_RING_RES");
+ case BTA_AG_CIND_RES: return ("AT Result BTA_AG_CIND_RES");
+ case BTA_AG_BINP_RES: return ("AT Result BTA_AG_BINP_RES");
+ case BTA_AG_IND_RES: return ("AT Result BTA_AG_IND_RES");
+ case BTA_AG_BVRA_RES: return ("AT Result BTA_AG_BVRA_RES");
+ case BTA_AG_CNUM_RES: return ("AT Result BTA_AG_CNUM_RES");
+ case BTA_AG_BTRH_RES: return ("AT Result BTA_AG_BTRH_RES");
+ case BTA_AG_CLCC_RES: return ("AT Result BTA_AG_CLCC_RES");
+ case BTA_AG_COPS_RES: return ("AT Result BTA_AG_COPS_RES");
+ case BTA_AG_IN_CALL_RES: return ("AT Result BTA_AG_IN_CALL_RES");
+ case BTA_AG_IN_CALL_CONN_RES: return ("AT Result BTA_AG_IN_CALL_CONN_RES");
+ case BTA_AG_CALL_WAIT_RES: return ("AT Result BTA_AG_CALL_WAIT_RES");
+ case BTA_AG_OUT_CALL_ORIG_RES: return ("AT Result BTA_AG_OUT_CALL_ORIG_RES");
+ case BTA_AG_OUT_CALL_ALERT_RES: return ("AT Result BTA_AG_OUT_CALL_ALERT_RES");
+ case BTA_AG_OUT_CALL_CONN_RES: return ("AT Result BTA_AG_OUT_CALL_CONN_RES");
+ case BTA_AG_CALL_CANCEL_RES: return ("AT Result BTA_AG_CALL_CANCEL_RES");
+ case BTA_AG_END_CALL_RES: return ("AT Result BTA_AG_END_CALL_RES");
+ case BTA_AG_UNAT_RES: return ("AT Result BTA_AG_UNAT_RES");
+ default: return ("Unknown AG Result");
+ }
+ case BTA_AG_API_SETCODEC_EVT:
+ return "Set Codec Request";
+ case BTA_AG_RFC_OPEN_EVT:
+ return "RFC Opened";
+ case BTA_AG_RFC_CLOSE_EVT:
+ return "RFC Closed";
+ case BTA_AG_RFC_SRV_CLOSE_EVT:
+ return "RFC SRV Closed";
+ case BTA_AG_RFC_DATA_EVT:
+ return "RFC Data";
+ case BTA_AG_SCO_OPEN_EVT:
+ return "Audio Opened";
+ case BTA_AG_SCO_CLOSE_EVT:
+ return "Audio Closed";
+ case BTA_AG_DISC_ACP_RES_EVT:
+ return "Discovery ACP Result";
+ case BTA_AG_DISC_INT_RES_EVT:
+ return "Discovery INT Result";
+ case BTA_AG_DISC_OK_EVT:
+ return "Discovery OK";
+ case BTA_AG_DISC_FAIL_EVT:
+ return "Discovery Failed";
+ case BTA_AG_CI_RX_WRITE_EVT:
+ return "CI RX Write";
+ case BTA_AG_RING_TOUT_EVT:
+ return "Ring Timeout";
+ case BTA_AG_SVC_TOUT_EVT:
+ return "Service Timeout";
+ case BTA_AG_API_ENABLE_EVT:
+ return "Enable AG";
+ case BTA_AG_API_DISABLE_EVT:
+ return "Disable AG";
+ case BTA_AG_CI_SCO_DATA_EVT:
+ return "SCO data Callin";
+ case BTA_AG_CI_SLC_READY_EVT:
+ return "SLC Ready Callin";
+ default:
+ return "Unknown AG Event";
+ }
+}
+
+static char *bta_ag_state_str(UINT8 state)
+{
+ switch (state)
+ {
+ case BTA_AG_INIT_ST:
+ return "Initial";
+ case BTA_AG_OPENING_ST:
+ return "Opening";
+ case BTA_AG_OPEN_ST:
+ return "Open";
+ case BTA_AG_CLOSING_ST:
+ return "Closing";
+ default:
+ return "Unknown AG State";
+ }
+}
+
+#endif
diff --git a/bta/ag/bta_ag_rfc.c b/bta/ag/bta_ag_rfc.c
new file mode 100644
index 0000000..3575020
--- /dev/null
+++ b/bta/ag/bta_ag_rfc.c
@@ -0,0 +1,441 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the audio gateway functions controlling the RFCOMM
+ * connections.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "bta_ag_co.h"
+#include "btm_api.h"
+#include "port_api.h"
+#include "rfcdefs.h"
+#include "gki.h"
+#include "bd.h"
+
+/* Event mask for RfCOMM port callback */
+#define BTA_AG_PORT_EV_MASK PORT_EV_RXCHAR
+
+/* each scb has its own rfcomm callbacks */
+void bta_ag_port_cback_1(UINT32 code, UINT16 port_handle);
+void bta_ag_port_cback_2(UINT32 code, UINT16 port_handle);
+void bta_ag_port_cback_3(UINT32 code, UINT16 port_handle);
+
+void bta_ag_mgmt_cback_1(UINT32 code, UINT16 port_handle);
+void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle);
+void bta_ag_mgmt_cback_3(UINT32 code, UINT16 port_handle);
+
+int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len);
+int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len);
+int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len);
+
+/* rfcomm callback function tables */
+typedef tPORT_CALLBACK *tBTA_AG_PORT_CBACK;
+const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] =
+{
+ bta_ag_port_cback_1,
+ bta_ag_port_cback_2,
+ bta_ag_port_cback_3
+};
+
+const tBTA_AG_PORT_CBACK bta_ag_mgmt_cback_tbl[] =
+{
+ bta_ag_mgmt_cback_1,
+ bta_ag_mgmt_cback_2,
+ bta_ag_mgmt_cback_3
+};
+
+typedef tPORT_DATA_CALLBACK *tBTA_AG_DATA_CBACK;
+const tBTA_AG_DATA_CBACK bta_ag_data_cback_tbl[] =
+{
+ bta_ag_data_cback_1,
+ bta_ag_data_cback_2,
+ bta_ag_data_cback_3
+};
+
+/*******************************************************************************
+**
+** Function bta_ag_port_cback
+**
+** Description RFCOMM Port callback
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_port_cback(UINT32 code, UINT16 port_handle, UINT16 handle)
+{
+ BT_HDR *p_buf;
+ tBTA_AG_SCB *p_scb;
+
+ if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL)
+ {
+ /* ignore port events for port handles other than connected handle */
+ if (port_handle != p_scb->conn_handle)
+ {
+ APPL_TRACE_DEBUG3("ag_port_cback ignoring handle:%d conn_handle = %d other handle = %d",
+ port_handle, p_scb->conn_handle, handle);
+ return;
+ }
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AG_RFC_DATA_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_mgmt_cback
+**
+** Description RFCOMM management callback
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_mgmt_cback(UINT32 code, UINT16 port_handle, UINT16 handle)
+{
+ tBTA_AG_RFC *p_buf;
+ tBTA_AG_SCB *p_scb;
+ UINT16 event;
+ UINT8 i;
+ BOOLEAN found_handle = FALSE;
+
+ APPL_TRACE_DEBUG3("ag_mgmt_cback : code = %d, port_handle = %d, handle = %d",
+ code, port_handle, handle);
+
+ if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL)
+ {
+ /* ignore close event for port handles other than connected handle */
+ if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle))
+ {
+ APPL_TRACE_DEBUG1("ag_mgmt_cback ignoring handle:%d", port_handle);
+ return;
+ }
+
+ if (code == PORT_SUCCESS)
+ {
+ if (p_scb->conn_handle) /* Outgoing connection */
+ {
+ if (port_handle == p_scb->conn_handle)
+ found_handle = TRUE;
+ }
+ else /* Incoming connection */
+ {
+ for (i = 0; i < BTA_AG_NUM_IDX; i++)
+ {
+ if (port_handle == p_scb->serv_handle[i])
+ found_handle = TRUE;
+ }
+ }
+
+ if (!found_handle)
+ {
+ APPL_TRACE_ERROR1 ("bta_ag_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle);
+ return;
+ }
+
+ event = BTA_AG_RFC_OPEN_EVT;
+ }
+ /* distinguish server close events */
+ else if (port_handle == p_scb->conn_handle)
+ {
+ event = BTA_AG_RFC_CLOSE_EVT;
+ }
+ else
+ {
+ event = BTA_AG_RFC_SRV_CLOSE_EVT;
+ }
+
+ if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL)
+ {
+ p_buf->hdr.event = event;
+ p_buf->hdr.layer_specific = handle;
+ p_buf->port_handle = port_handle;
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_data_cback
+**
+** Description RFCOMM data callback
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static int bta_ag_data_cback(UINT16 port_handle, void *p_data, UINT16 len, UINT16 handle)
+{
+ /* call data call-out directly */
+ bta_ag_co_tx_write(handle, (UINT8 *) p_data, len);
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_port_cback_1 to 3
+** bta_ag_mgmt_cback_1 to 3
+**
+** Description RFCOMM callback functions. This is an easy way to
+** distinguish scb from the callback.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 1);}
+void bta_ag_mgmt_cback_2(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 2);}
+void bta_ag_mgmt_cback_3(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 3);}
+void bta_ag_port_cback_1(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 1);}
+void bta_ag_port_cback_2(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 2);}
+void bta_ag_port_cback_3(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 3);}
+
+/*******************************************************************************
+**
+** Function bta_ag_data_cback_1 to 3
+**
+** Description RFCOMM data callback functions. This is an easy way to
+** distinguish scb from the callback.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len)
+{
+ return bta_ag_data_cback(port_handle, p_data, len, 1);
+}
+int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len)
+{
+ return bta_ag_data_cback(port_handle, p_data, len, 2);
+}
+int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len)
+{
+ return bta_ag_data_cback(port_handle, p_data, len, 3);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_setup_port
+**
+** Description Setup RFCOMM port for use by AG.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_setup_port(tBTA_AG_SCB *p_scb, UINT16 handle)
+{
+ UINT16 i = bta_ag_scb_to_idx(p_scb) - 1;
+
+ /* set up data callback if using pass through mode */
+ if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH)
+ {
+ PORT_SetDataCallback(handle, bta_ag_data_cback_tbl[i]);
+ }
+
+ PORT_SetEventMask(handle, BTA_AG_PORT_EV_MASK);
+ PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[i]);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_start_servers
+**
+** Description Setup RFCOMM servers for use by AG.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_start_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services)
+{
+ int i;
+ int bta_ag_port_status;
+
+ services >>= BTA_HSP_SERVICE_ID;
+ for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1)
+ {
+ /* if service is set in mask */
+ if (services & 1)
+ {
+ BTM_SetSecurityLevel(FALSE, "", bta_ag_sec_id[i], p_scb->serv_sec_mask,
+ BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_ag_cb.profile[i].scn);
+
+ bta_ag_port_status = RFCOMM_CreateConnection(bta_ag_uuid[i], bta_ag_cb.profile[i].scn,
+ TRUE, BTA_AG_MTU, (UINT8 *) bd_addr_any, &(p_scb->serv_handle[i]),
+ bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
+
+ if( bta_ag_port_status == PORT_SUCCESS )
+ {
+ bta_ag_setup_port(p_scb, p_scb->serv_handle[i]);
+ }
+ else
+ {
+ /* TODO: CR#137125 to handle to error properly */
+ APPL_TRACE_DEBUG1("bta_ag_start_servers: RFCOMM_CreateConnection returned error:%d", bta_ag_port_status);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_close_servers
+**
+** Description Close RFCOMM servers port for use by AG.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_close_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services)
+{
+ int i;
+
+ services >>= BTA_HSP_SERVICE_ID;
+ for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1)
+ {
+ /* if service is set in mask */
+ if (services & 1)
+ {
+ RFCOMM_RemoveServer(p_scb->serv_handle[i]);
+ p_scb->serv_handle[i] = 0;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_is_server_closed
+**
+** Description Returns TRUE if all servers are closed.
+**
+**
+** Returns TRUE if all servers are closed, FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN bta_ag_is_server_closed (tBTA_AG_SCB *p_scb)
+{
+ UINT8 xx;
+ BOOLEAN is_closed = TRUE;
+
+ for (xx = 0; xx < BTA_AG_NUM_IDX; xx++)
+ {
+ if (p_scb->serv_handle[xx] != 0)
+ is_closed = FALSE;
+ }
+
+ return is_closed;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_rfc_do_open
+**
+** Description Open an RFCOMM connection to the peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_rfc_do_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ BTM_SetSecurityLevel(TRUE, "", bta_ag_sec_id[p_scb->conn_service],
+ p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, p_scb->peer_scn);
+
+ if (RFCOMM_CreateConnection(bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn,
+ FALSE, BTA_AG_MTU, p_scb->peer_addr, &(p_scb->conn_handle),
+ bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]) == PORT_SUCCESS)
+ {
+ bta_ag_setup_port(p_scb, p_scb->conn_handle);
+ APPL_TRACE_DEBUG1("bta_ag_rfc_do_open : conn_handle = %d", p_scb->conn_handle);
+ }
+ /* RFCOMM create connection failed; send ourselves RFCOMM close event */
+ else
+ {
+ bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_rfc_do_close
+**
+** Description Close RFCOMM connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_rfc_do_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ tBTA_AG_RFC *p_buf;
+
+ if (p_scb->conn_handle)
+ {
+ RFCOMM_RemoveConnection(p_scb->conn_handle);
+ }
+ else
+ {
+ /* Close API was called while AG is in Opening state. */
+ /* Need to trigger the state machine to send callback to the app */
+ /* and move back to INIT state. */
+ if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT;
+ p_buf->hdr.layer_specific = bta_ag_scb_to_idx(p_scb);
+ bta_sys_sendmsg(p_buf);
+ }
+
+ /* Cancel SDP if it had been started. */
+ /*
+ if(p_scb->p_disc_db)
+ {
+ (void)SDP_CancelServiceSearch (p_scb->p_disc_db);
+ }
+ */
+ }
+
+#ifdef _WIN32_WCE
+ {
+ /* Windows versions of RFCOMM does NOT generate a closed callback when we close */
+ tPORT_CALLBACK *rfc_mgmt_cback = bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1];
+
+ if (rfc_mgmt_cback)
+ {
+ (rfc_mgmt_cback)(PORT_CLOSED, p_scb->conn_handle);
+ }
+ }
+#endif
+}
+
diff --git a/bta/ag/bta_ag_sco.c b/bta/ag/bta_ag_sco.c
new file mode 100644
index 0000000..0c811b4
--- /dev/null
+++ b/bta/ag/bta_ag_sco.c
@@ -0,0 +1,1662 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains functions for managing the SCO connection used in AG.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_ag_api.h"
+#include "bta_ag_co.h"
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+#include "bta_dm_co.h"
+#endif
+#include "bta_ag_int.h"
+#include "btm_api.h"
+#include "gki.h"
+
+#ifndef BTA_AG_SCO_DEBUG
+#define BTA_AG_SCO_DEBUG FALSE
+#endif
+
+#ifndef BTA_AG_CODEC_NEGO_TIMEOUT
+#define BTA_AG_CODEC_NEGO_TIMEOUT 3000
+#endif
+
+#if BTA_AG_SCO_DEBUG == TRUE
+static char *bta_ag_sco_evt_str(UINT8 event);
+static char *bta_ag_sco_state_str(UINT8 state);
+#endif
+
+#define BTA_AG_NO_EDR_ESCO (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
+
+/* sco events */
+enum
+{
+ BTA_AG_SCO_LISTEN_E, /* listen request */
+ BTA_AG_SCO_OPEN_E, /* open request */
+ BTA_AG_SCO_XFER_E, /* transfer request */
+#if (BTM_WBS_INCLUDED == TRUE )
+ BTA_AG_SCO_CN_DONE_E, /* codec negotiation done */
+ BTA_AG_SCO_REOPEN_E, /* Retry with other codec when failed */
+#endif
+ BTA_AG_SCO_CLOSE_E, /* close request */
+ BTA_AG_SCO_SHUTDOWN_E, /* shutdown request */
+ BTA_AG_SCO_CONN_OPEN_E, /* sco open */
+ BTA_AG_SCO_CONN_CLOSE_E, /* sco closed */
+ BTA_AG_SCO_CI_DATA_E /* SCO data ready */
+};
+
+#if (BTM_WBS_INCLUDED == TRUE )
+#define BTA_AG_NUM_CODECS 2
+static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
+{
+ /* CVSD */
+ {
+ BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
+ BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
+ 0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
+ BTM_VOICE_SETTING_CVSD, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
+ (BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
+ BTM_SCO_PKT_TYPES_MASK_HV2 +
+ BTM_SCO_PKT_TYPES_MASK_HV3 +
+ BTM_SCO_PKT_TYPES_MASK_EV3 +
+ BTM_SCO_PKT_TYPES_MASK_EV4 +
+ BTM_SCO_PKT_TYPES_MASK_EV5 +
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+ BTM_ESCO_RETRANS_POWER /* Retransmission effort */
+ },
+ /* mSBC */
+ {
+ BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec), 8000 */
+ BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec), 8000 */
+ 13, /* 13 ms */
+ BTM_VOICE_SETTING_TRANS, /* Inp Linear, Transparent, 2s Comp, 16bit */
+ (BTM_SCO_PKT_TYPES_MASK_EV3 | /* Packet Types : EV3 + 2-EV3 */
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+ BTM_ESCO_RETRANS_QUALITY /* Retransmission effort */
+ }
+};
+#else
+static const tBTM_ESCO_PARAMS bta_ag_esco_params =
+{
+ BTM_64KBITS_RATE, /* TX Bandwidth (64 kbits/sec) */
+ BTM_64KBITS_RATE, /* RX Bandwidth (64 kbits/sec) */
+ 0x000a, /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3) */
+ 0x0060, /* Inp Linear, Air CVSD, 2s Comp, 16bit */
+ (BTM_SCO_PKT_TYPES_MASK_HV1 + /* Packet Types */
+ BTM_SCO_PKT_TYPES_MASK_HV2 +
+ BTM_SCO_PKT_TYPES_MASK_HV3 +
+ BTM_SCO_PKT_TYPES_MASK_EV3 +
+ BTM_SCO_PKT_TYPES_MASK_EV4 +
+ BTM_SCO_PKT_TYPES_MASK_EV5 +
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+ BTM_ESCO_RETRANS_POWER /* Retransmission effort */
+};
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_conn_cback
+**
+** Description BTM SCO connection callback.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_sco_conn_cback(UINT16 sco_idx)
+{
+ UINT16 handle;
+ BT_HDR *p_buf;
+ tBTA_AG_SCB *p_scb;
+
+ /* match callback to scb; first check current sco scb */
+ if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use)
+ {
+ handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
+ }
+ /* then check for scb connected to this peer */
+ else
+ {
+ /* Check if SLC is up */
+ handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_idx));
+ p_scb = bta_ag_scb_by_idx(handle);
+ if(p_scb && !p_scb->svc_conn)
+ handle = 0;
+ }
+
+ if (handle != 0)
+ {
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AG_SCO_OPEN_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+ /* no match found; disconnect sco, init sco variables */
+ else
+ {
+ bta_ag_cb.sco.p_curr_scb = NULL;
+ bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
+ BTM_RemoveSco(sco_idx);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_disc_cback
+**
+** Description BTM SCO disconnection callback.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_sco_disc_cback(UINT16 sco_idx)
+{
+ BT_HDR *p_buf;
+ UINT16 handle = 0;
+
+ APPL_TRACE_DEBUG3 ("bta_ag_sco_disc_cback(): sco_idx: 0x%x p_cur_scb: 0x%08x sco.state: %d", sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state);
+
+ APPL_TRACE_DEBUG4 ("bta_ag_sco_disc_cback(): scb[0] addr: 0x%08x in_use: %u sco_idx: 0x%x sco state: %u",
+ &bta_ag_cb.scb[0], bta_ag_cb.scb[0].in_use, bta_ag_cb.scb[0].sco_idx, bta_ag_cb.scb[0].state);
+ APPL_TRACE_DEBUG4 ("bta_ag_sco_disc_cback(): scb[1] addr: 0x%08x in_use: %u sco_idx: 0x%x sco state: %u",
+ &bta_ag_cb.scb[1], bta_ag_cb.scb[1].in_use, bta_ag_cb.scb[1].sco_idx, bta_ag_cb.scb[1].state);
+
+ /* match callback to scb */
+ if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use)
+ {
+ /* We only care about callbacks for the active SCO */
+ if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx)
+ {
+ if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF)
+ return;
+ }
+ handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
+ }
+
+ if (handle != 0)
+ {
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE);
+ APPL_TRACE_DEBUG1("bta_ag_sco_disc_cback sco close config status = %d", status);
+ /* SCO clean up here */
+ bta_dm_sco_co_close();
+#endif
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ /* Restore settings */
+ if(bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC)
+ {
+ BTM_SetWBSCodec (BTM_SCO_CODEC_NONE);
+ BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
+
+ /* If SCO open was initiated by AG and failed for mSBC, try CVSD again. */
+ if (bta_ag_sco_is_opening (bta_ag_cb.sco.p_curr_scb))
+ {
+ bta_ag_cb.sco.p_curr_scb->codec_fallback = TRUE;
+ APPL_TRACE_DEBUG0("Fallback to CVSD");
+ }
+ }
+
+ bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE;
+#endif
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AG_SCO_CLOSE_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+ /* no match found */
+ else
+ {
+ APPL_TRACE_DEBUG0("no scb for ag_sco_disc_cback");
+
+ /* sco could be closed after scb dealloc'ed */
+ if (bta_ag_cb.sco.p_curr_scb != NULL)
+ {
+ bta_ag_cb.sco.p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+ bta_ag_cb.sco.p_curr_scb = NULL;
+ bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
+ }
+ }
+}
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function bta_ag_sco_read_cback
+**
+** Description Callback function is the callback function for incoming
+** SCO data over HCI.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_sco_read_cback (UINT16 sco_inx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status)
+{
+ if (status != BTM_SCO_DATA_CORRECT)
+ {
+ APPL_TRACE_DEBUG1("bta_ag_sco_read_cback: status(%d)", status);
+ }
+
+ /* Callout function must free the data. */
+ bta_dm_sco_co_in_data (p_data, status);
+}
+#endif
+/*******************************************************************************
+**
+** Function bta_ag_remove_sco
+**
+** Description Removes the specified SCO from the system.
+** If only_active is TRUE, then SCO is only removed if connected
+**
+** Returns BOOLEAN - TRUE if Sco removal was started
+**
+*******************************************************************************/
+static BOOLEAN bta_ag_remove_sco(tBTA_AG_SCB *p_scb, BOOLEAN only_active)
+{
+ BOOLEAN removed_started = FALSE;
+ tBTM_STATUS status;
+
+ if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
+ {
+ if (!only_active || p_scb->sco_idx == bta_ag_cb.sco.cur_idx)
+ {
+ status = BTM_RemoveSco(p_scb->sco_idx);
+
+ APPL_TRACE_DEBUG2("ag remove sco: inx 0x%04x, status:0x%x", p_scb->sco_idx, status);
+
+ if (status == BTM_CMD_STARTED)
+ {
+ /* Sco is connected; set current control block */
+ bta_ag_cb.sco.p_curr_scb = p_scb;
+
+ removed_started = TRUE;
+ }
+ /* If no connection reset the sco handle */
+ else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) )
+ {
+ p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+ }
+ }
+ }
+ return removed_started;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ag_esco_connreq_cback
+**
+** Description BTM eSCO connection requests and eSCO change requests
+** Only the connection requests are processed by BTA.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
+{
+ tBTA_AG_SCB *p_scb;
+ UINT16 handle;
+ UINT16 sco_inx = p_data->conn_evt.sco_inx;
+
+ /* Only process connection requests */
+ if (event == BTM_ESCO_CONN_REQ_EVT)
+ {
+ if ((handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_inx))) != 0 &&
+ ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) && p_scb->svc_conn)
+ {
+ p_scb->sco_idx = sco_inx;
+
+ /* If no other SCO active, allow this one */
+ if (!bta_ag_cb.sco.p_curr_scb)
+ {
+ APPL_TRACE_EVENT1("bta_ag_esco_connreq_cback: Accept Conn Request (sco_inx 0x%04x)", sco_inx);
+ bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
+
+ bta_ag_cb.sco.state = BTA_AG_SCO_OPENING_ST;
+ bta_ag_cb.sco.p_curr_scb = p_scb;
+ bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
+ }
+ else /* Begin a transfer: Close current SCO before responding */
+ {
+ APPL_TRACE_DEBUG0("bta_ag_esco_connreq_cback: Begin XFER");
+ bta_ag_cb.sco.p_xfer_scb = p_scb;
+ bta_ag_cb.sco.conn_data = p_data->conn_evt;
+ bta_ag_cb.sco.state = BTA_AG_SCO_OPEN_XFER_ST;
+
+ if (!bta_ag_remove_sco(bta_ag_cb.sco.p_curr_scb, TRUE))
+ {
+ APPL_TRACE_ERROR1("bta_ag_esco_connreq_cback: Nothing to remove so accept Conn Request (sco_inx 0x%04x)", sco_inx);
+ bta_ag_cb.sco.p_xfer_scb = NULL;
+ bta_ag_cb.sco.state = BTA_AG_SCO_LISTEN_ST;
+
+ bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
+ }
+ }
+ }
+ /* If error occurred send reject response immediately */
+ else
+ {
+ APPL_TRACE_WARNING0("no scb for bta_ag_esco_connreq_cback or no resources");
+ BTM_EScoConnRsp(p_data->conn_evt.sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, NULL);
+ }
+ }
+ /* Received a change in the esco link */
+ else if (event == BTM_ESCO_CHG_EVT)
+ {
+ APPL_TRACE_EVENT5("eSCO change event (inx %d): rtrans %d, rxlen %d, txlen %d, txint %d",
+ p_data->chg_evt.sco_inx,
+ p_data->chg_evt.retrans_window, p_data->chg_evt.rx_pkt_len,
+ p_data->chg_evt.tx_pkt_len, p_data->chg_evt.tx_interval);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_cback_sco
+**
+** Description Call application callback function with SCO event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_cback_sco(tBTA_AG_SCB *p_scb, UINT8 event)
+{
+ tBTA_AG_HDR sco;
+
+ sco.handle = bta_ag_scb_to_idx(p_scb);
+ sco.app_id = p_scb->app_id;
+
+ /* call close cback */
+ (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &sco);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_create_sco
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
+{
+ tBTM_STATUS status;
+ UINT8 *p_bd_addr = NULL;
+ tBTM_ESCO_PARAMS params;
+#if (BTM_WBS_INCLUDED == TRUE )
+ tBTA_AG_PEER_CODEC esco_codec = BTM_SCO_CODEC_CVSD;
+ int codec_index = 0;
+#endif
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ tBTM_SCO_ROUTE_TYPE sco_route;
+ tBTA_CODEC_INFO codec_info = {BTA_SCO_CODEC_PCM};
+ UINT32 pcm_sample_rate;
+#endif
+
+ /* Make sure this sco handle is not already in use */
+ if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
+ {
+ APPL_TRACE_WARNING1("bta_ag_create_sco: Index 0x%04x Already In Use!",
+ p_scb->sco_idx);
+ return;
+ }
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ if ((p_scb->sco_codec == BTM_SCO_CODEC_MSBC) &&
+ !p_scb->codec_fallback &&
+ !p_scb->retry_with_sco_only)
+ esco_codec = BTM_SCO_CODEC_MSBC;
+
+ if (p_scb->codec_fallback)
+ {
+ p_scb->codec_fallback = FALSE;
+
+ /* Force AG to send +BCS for the next audio connection. */
+ p_scb->codec_updated = TRUE;
+ }
+
+ if (esco_codec == BTM_SCO_CODEC_MSBC)
+ codec_index = esco_codec - 1;
+
+ params = bta_ag_esco_params[codec_index];
+#else
+ params = bta_ag_esco_params;
+#endif
+
+ if(bta_ag_cb.sco.param_updated) /* If we do not use the default parameters */
+ params = bta_ag_cb.sco.params;
+
+ if(!bta_ag_cb.sco.param_updated)
+ {
+#if (BTM_WBS_INCLUDED == TRUE)
+ if (!codec_index) /* For non-WBS */
+#endif
+ {
+ /* Use the application packet types (5 slot EV packets not allowed) */
+ params.packet_types = p_bta_ag_cfg->sco_pkt_types |
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
+ }
+ }
+
+ /* if initiating set current scb and peer bd addr */
+ if (is_orig)
+ {
+ /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
+ /* Need to find out from SIG if HSP can use eSCO; for now use SCO */
+ if (p_scb->conn_service == BTA_AG_HFP && p_scb->peer_version >= HFP_VERSION_1_5 && !p_scb->retry_with_sco_only)
+ {
+
+ BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, ¶ms);
+ /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
+ if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
+ ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_AG_NO_EDR_ESCO))
+ {
+#if (BTM_WBS_INCLUDED == TRUE )
+ if (esco_codec != BTA_AG_CODEC_MSBC)
+ {
+ p_scb->retry_with_sco_only = TRUE;
+ APPL_TRACE_API0("Setting retry_with_sco_only to TRUE");
+ }
+ else /* Do not use SCO when using mSBC */
+ {
+ p_scb->retry_with_sco_only = FALSE;
+ APPL_TRACE_API0("Setting retry_with_sco_only to FALSE");
+ }
+#else
+ p_scb->retry_with_sco_only = TRUE;
+ APPL_TRACE_API0("Setting retry_with_sco_only to TRUE");
+#endif
+ }
+ }
+ else
+ {
+ if(p_scb->retry_with_sco_only)
+ APPL_TRACE_API0("retrying with SCO only");
+ p_scb->retry_with_sco_only = FALSE;
+
+ BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms);
+ }
+
+ bta_ag_cb.sco.p_curr_scb = p_scb;
+
+ /* tell sys to stop av if any */
+ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ /* Allow any platform specific pre-SCO set up to take place */
+ bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP);
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+#if (BTM_WBS_INCLUDED == TRUE)
+ if (esco_codec == BTA_AG_CODEC_MSBC)
+ pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_16K;
+ else
+#endif
+ pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
+
+ sco_route = bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id);
+#endif
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ if (esco_codec == BTA_AG_CODEC_MSBC)
+ {
+ /* Enable mSBC codec in fw */
+ BTM_SetWBSCodec (esco_codec);
+ }
+
+ /* Specify PCM input for SBC codec in fw */
+ BTM_ConfigI2SPCM (esco_codec, (UINT8)HCI_BRCM_I2SPCM_IS_DEFAULT_ROLE, (UINT8)HCI_BRCM_I2SPCM_SAMPLE_DEFAULT, (UINT8)HCI_BRCM_I2SPCM_CLOCK_DEFAULT);
+
+ /* This setting may not be necessary */
+ /* To be verified with stable 2049 boards */
+ if (esco_codec == BTA_AG_CODEC_MSBC)
+ BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS);
+ else
+ BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
+
+ /* save the current codec because sco_codec can be updated while SCO is open. */
+ p_scb->inuse_codec = esco_codec;
+#endif
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
+ BTM_ConfigScoPath(sco_route, bta_ag_sco_read_cback, NULL, TRUE);
+#endif
+ bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
+ }
+ else
+ p_scb->retry_with_sco_only = FALSE;
+
+ p_bd_addr = p_scb->peer_addr;
+
+ status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
+ &p_scb->sco_idx, bta_ag_sco_conn_cback,
+ bta_ag_sco_disc_cback);
+ if (status == BTM_CMD_STARTED)
+ {
+ if (!is_orig)
+ {
+ BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
+ }
+ else /* Initiating the connection, set the current sco handle */
+ {
+ bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
+ }
+ }
+
+ APPL_TRACE_API4("ag create sco: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
+ is_orig, p_scb->sco_idx, status, params.packet_types);
+}
+
+#if (BTM_WBS_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function bta_ag_cn_timer_cback
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_cn_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+ tBTA_AG_SCB *p_scb;
+
+ if (p_tle)
+ {
+ p_scb = (tBTA_AG_SCB *)p_tle->param;
+
+ if (p_scb)
+ {
+ /* Announce that codec negotiation failed. */
+ bta_ag_sco_codec_nego(p_scb, FALSE);
+
+ /* call app callback */
+ bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_codec_negotiate
+**
+** Description Initiate codec negotiation by sending AT command.
+** If not necessary, skip negotiation.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb)
+{
+ bta_ag_cb.sco.p_curr_scb = p_scb;
+
+ if (p_scb->codec_updated || p_scb->codec_fallback)
+ {
+ /* Change the power mode to Active until sco open is completed. */
+ bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ /* Send +BCS to the peer */
+ bta_ag_send_bcs(p_scb, NULL);
+
+ /* Start timer to handle timeout */
+ p_scb->cn_timer.p_cback = (TIMER_CBACK*)&bta_ag_cn_timer_cback;
+ p_scb->cn_timer.param = (INT32)p_scb;
+ bta_sys_start_timer(&p_scb->cn_timer, 0, BTA_AG_CODEC_NEGO_TIMEOUT);
+ }
+ else
+ {
+ /* use same codec type as previous SCO connection, skip codec negotiation */
+ bta_ag_sco_codec_nego(p_scb, TRUE);
+ }
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_event
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event)
+{
+ tBTA_AG_SCO_CB *p_sco = &bta_ag_cb.sco;
+#if (BTM_WBS_INCLUDED == TRUE )
+ tBTA_AG_SCB *p_cn_scb = NULL; /* For codec negotiation */
+#endif
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ BT_HDR *p_buf;
+#endif
+#if BTA_AG_SCO_DEBUG == TRUE
+ UINT8 in_state = p_sco->state;
+
+ APPL_TRACE_EVENT5("BTA ag sco evt (hdl 0x%04x): State %d (%s), Event %d (%s)",
+ p_scb->sco_idx,
+ p_sco->state, bta_ag_sco_state_str(p_sco->state),
+ event, bta_ag_sco_evt_str(event));
+#else
+ APPL_TRACE_EVENT3("BTA ag sco evt (hdl 0x%04x): State %d, Event %d",
+ p_scb->sco_idx, p_sco->state, event);
+#endif
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ if (event == BTA_AG_SCO_CI_DATA_E)
+ {
+ while (TRUE)
+ {
+ bta_dm_sco_co_out_data(&p_buf);
+ if (p_buf)
+ {
+ if (p_sco->state == BTA_AG_SCO_OPEN_ST)
+ BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf);
+ else
+ GKI_freebuf(p_buf);
+ }
+ else
+ break;
+ }
+
+ return;
+ }
+#endif
+
+ switch (p_sco->state)
+ {
+ case BTA_AG_SCO_SHUTDOWN_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_LISTEN_E:
+ /* create sco listen connection */
+ bta_ag_create_sco(p_scb, FALSE);
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ case BTA_AG_SCO_LISTEN_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_LISTEN_E:
+ /* create sco listen connection (Additional channel) */
+ bta_ag_create_sco(p_scb, FALSE);
+ break;
+
+ case BTA_AG_SCO_OPEN_E:
+ /* remove listening connection */
+ bta_ag_remove_sco(p_scb, FALSE);
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ /* start codec negotiation */
+ p_sco->state = BTA_AG_SCO_CODEC_ST;
+ p_cn_scb = p_scb;
+#else
+ /* create sco connection to peer */
+ bta_ag_create_sco(p_scb, TRUE);
+ p_sco->state = BTA_AG_SCO_OPENING_ST;
+#endif
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* remove listening connection */
+ bta_ag_remove_sco(p_scb, FALSE);
+
+ if (p_scb == p_sco->p_curr_scb)
+ p_sco->p_curr_scb = NULL;
+
+ /* If last SCO instance then finish shutting down */
+ if (!bta_ag_other_scb_open(p_scb))
+ {
+ p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+ }
+ break;
+
+ case BTA_AG_SCO_CLOSE_E:
+ /* remove listening connection */
+ /* Ignore the event. We need to keep listening SCO for the active SLC */
+ APPL_TRACE_WARNING1("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event);
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* sco failed; create sco listen connection */
+ bta_ag_create_sco(p_scb, FALSE);
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ case BTA_AG_SCO_CODEC_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_LISTEN_E:
+ /* create sco listen connection (Additional channel) */
+ bta_ag_create_sco(p_scb, FALSE);
+ break;
+
+ case BTA_AG_SCO_CN_DONE_E:
+ /* create sco connection to peer */
+ bta_ag_create_sco(p_scb, TRUE);
+ p_sco->state = BTA_AG_SCO_OPENING_ST;
+ break;
+
+ case BTA_AG_SCO_XFER_E:
+ /* save xfer scb */
+ p_sco->p_xfer_scb = p_scb;
+ p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* remove listening connection */
+ bta_ag_remove_sco(p_scb, FALSE);
+
+ if (p_scb == p_sco->p_curr_scb)
+ p_sco->p_curr_scb = NULL;
+
+ /* If last SCO instance then finish shutting down */
+ if (!bta_ag_other_scb_open(p_scb))
+ {
+ p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+ }
+ break;
+
+ case BTA_AG_SCO_CLOSE_E:
+ /* sco open is not started yet. just go back to listening */
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* sco failed; create sco listen connection */
+ bta_ag_create_sco(p_scb, FALSE);
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_CODEC_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+#endif
+
+ case BTA_AG_SCO_OPENING_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_LISTEN_E:
+ /* second headset has now joined */
+ /* create sco listen connection (Additional channel) */
+ if (p_scb != p_sco->p_curr_scb)
+ {
+ bta_ag_create_sco(p_scb, FALSE);
+ }
+ break;
+
+#if (BTM_WBS_INCLUDED == TRUE)
+ case BTA_AG_SCO_REOPEN_E:
+ /* start codec negotiation */
+ p_sco->state = BTA_AG_SCO_CODEC_ST;
+ p_cn_scb = p_scb;
+ break;
+#endif
+
+ case BTA_AG_SCO_XFER_E:
+ /* save xfer scb */
+ p_sco->p_xfer_scb = p_scb;
+ p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+ break;
+
+ case BTA_AG_SCO_CLOSE_E:
+ p_sco->state = BTA_AG_SCO_OPEN_CL_ST;
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* If not opening scb, just close it */
+ if (p_scb != p_sco->p_curr_scb)
+ {
+ /* remove listening connection */
+ bta_ag_remove_sco(p_scb, FALSE);
+ }
+ else
+ p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+
+ break;
+
+ case BTA_AG_SCO_CONN_OPEN_E:
+ p_sco->state = BTA_AG_SCO_OPEN_ST;
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* sco failed; create sco listen connection */
+ bta_ag_create_sco(p_scb, FALSE);
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_OPENING_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ case BTA_AG_SCO_OPEN_CL_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_XFER_E:
+ /* save xfer scb */
+ p_sco->p_xfer_scb = p_scb;
+
+ p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+ break;
+
+ case BTA_AG_SCO_OPEN_E:
+ p_sco->state = BTA_AG_SCO_OPENING_ST;
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* If not opening scb, just close it */
+ if (p_scb != p_sco->p_curr_scb)
+ {
+ /* remove listening connection */
+ bta_ag_remove_sco(p_scb, FALSE);
+ }
+ else
+ p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+
+ break;
+
+ case BTA_AG_SCO_CONN_OPEN_E:
+ /* close sco connection */
+ bta_ag_remove_sco(p_scb, TRUE);
+
+ p_sco->state = BTA_AG_SCO_CLOSING_ST;
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* sco failed; create sco listen connection */
+
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ case BTA_AG_SCO_OPEN_XFER_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_CLOSE_E:
+ /* close sco connection */
+ bta_ag_remove_sco(p_scb, TRUE);
+
+ p_sco->state = BTA_AG_SCO_CLOSING_ST;
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* remove all connection */
+ bta_ag_remove_sco(p_scb, FALSE);
+ p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* closed sco; place in listen mode and
+ accept the transferred connection */
+ bta_ag_create_sco(p_scb, FALSE); /* Back into listen mode */
+
+ /* Accept sco connection with xfer scb */
+ bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data);
+ p_sco->state = BTA_AG_SCO_OPENING_ST;
+ p_sco->p_curr_scb = p_sco->p_xfer_scb;
+ p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
+ p_sco->p_xfer_scb = NULL;
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ case BTA_AG_SCO_OPEN_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_LISTEN_E:
+ /* second headset has now joined */
+ /* create sco listen connection (Additional channel) */
+ if (p_scb != p_sco->p_curr_scb)
+ {
+ bta_ag_create_sco(p_scb, FALSE);
+ }
+ break;
+
+ case BTA_AG_SCO_XFER_E:
+ /* close current sco connection */
+ bta_ag_remove_sco(p_sco->p_curr_scb, TRUE);
+
+ /* save xfer scb */
+ p_sco->p_xfer_scb = p_scb;
+
+ p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+ break;
+
+ case BTA_AG_SCO_CLOSE_E:
+ /* close sco connection if active */
+ if (bta_ag_remove_sco(p_scb, TRUE))
+ {
+ p_sco->state = BTA_AG_SCO_CLOSING_ST;
+ }
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* remove all listening connections */
+ bta_ag_remove_sco(p_scb, FALSE);
+
+ /* If SCO was active on this scb, close it */
+ if (p_scb == p_sco->p_curr_scb)
+ {
+ p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+ }
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* peer closed sco; create sco listen connection */
+ bta_ag_create_sco(p_scb, FALSE);
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ case BTA_AG_SCO_CLOSING_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_LISTEN_E:
+ /* create sco listen connection (Additional channel) */
+ if (p_scb != p_sco->p_curr_scb)
+ {
+ bta_ag_create_sco(p_scb, FALSE);
+ }
+ break;
+
+ case BTA_AG_SCO_OPEN_E:
+ p_sco->state = BTA_AG_SCO_CLOSE_OP_ST;
+ break;
+
+ case BTA_AG_SCO_XFER_E:
+ /* save xfer scb */
+ p_sco->p_xfer_scb = p_scb;
+
+ p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* If not closing scb, just close it */
+ if (p_scb != p_sco->p_curr_scb)
+ {
+ /* remove listening connection */
+ bta_ag_remove_sco(p_scb, FALSE);
+ }
+ else
+ p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* peer closed sco; create sco listen connection */
+ bta_ag_create_sco(p_scb, FALSE);
+
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSING_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ case BTA_AG_SCO_CLOSE_OP_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_CLOSE_E:
+ p_sco->state = BTA_AG_SCO_CLOSING_ST;
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+#if (BTM_WBS_INCLUDED == TRUE )
+ /* start codec negotiation */
+ p_sco->state = BTA_AG_SCO_CODEC_ST;
+ p_cn_scb = p_scb;
+#else
+ /* open sco connection */
+ bta_ag_create_sco(p_scb, TRUE);
+ p_sco->state = BTA_AG_SCO_OPENING_ST;
+#endif
+ break;
+
+ case BTA_AG_SCO_LISTEN_E:
+ /* create sco listen connection (Additional channel) */
+ if (p_scb != p_sco->p_curr_scb)
+ {
+ bta_ag_create_sco(p_scb, FALSE);
+ }
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ case BTA_AG_SCO_CLOSE_XFER_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_CONN_OPEN_E:
+ /* close sco connection so headset can be transferred
+ Probably entered this state from "opening state" */
+ bta_ag_remove_sco(p_scb, TRUE);
+ break;
+
+ case BTA_AG_SCO_CLOSE_E:
+ /* clear xfer scb */
+ p_sco->p_xfer_scb = NULL;
+
+ p_sco->state = BTA_AG_SCO_CLOSING_ST;
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ /* clear xfer scb */
+ p_sco->p_xfer_scb = NULL;
+
+ p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* closed sco; place old sco in listen mode,
+ take current sco out of listen, and
+ create originating sco for current */
+ bta_ag_create_sco(p_scb, FALSE);
+ bta_ag_remove_sco(p_sco->p_xfer_scb, FALSE);
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ /* start codec negotiation */
+ p_sco->state = BTA_AG_SCO_CODEC_ST;
+ p_cn_scb = p_sco->p_xfer_scb;
+ p_sco->p_xfer_scb = NULL;
+#else
+ /* create sco connection to peer */
+ bta_ag_create_sco(p_sco->p_xfer_scb, TRUE);
+ p_sco->p_xfer_scb = NULL;
+ p_sco->state = BTA_AG_SCO_OPENING_ST;
+#endif
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ case BTA_AG_SCO_SHUTTING_ST:
+ switch (event)
+ {
+ case BTA_AG_SCO_CONN_OPEN_E:
+ /* close sco connection; wait for conn close event */
+ bta_ag_remove_sco(p_scb, TRUE);
+ break;
+
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ /* If last SCO instance then finish shutting down */
+ if (!bta_ag_other_scb_open(p_scb))
+ {
+ p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+ }
+ else /* Other instance is still listening */
+ {
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ }
+
+ if (p_scb == p_sco->p_curr_scb)
+ {
+ p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+ p_sco->p_curr_scb = NULL;
+ }
+ break;
+
+ case BTA_AG_SCO_LISTEN_E:
+ /* create sco listen connection (Additional channel) */
+ if (p_scb != p_sco->p_curr_scb)
+ {
+ bta_ag_create_sco(p_scb, FALSE);
+ }
+ break;
+
+ case BTA_AG_SCO_SHUTDOWN_E:
+ if (!bta_ag_other_scb_open(p_scb))
+ {
+ p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+ }
+ else /* Other instance is still listening */
+ {
+ p_sco->state = BTA_AG_SCO_LISTEN_ST;
+ }
+
+ if (p_scb == p_sco->p_curr_scb)
+ {
+ p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+ p_sco->p_curr_scb = NULL;
+ }
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("BTA_AG_SCO_SHUTTING_ST: Ignoring event %d", event);
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+#if BTA_AG_SCO_DEBUG == TRUE
+ if (p_sco->state != in_state)
+ {
+ APPL_TRACE_EVENT3("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
+ bta_ag_sco_state_str(in_state),
+ bta_ag_sco_state_str(p_sco->state),
+ bta_ag_sco_evt_str(event));
+ }
+#endif
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ if (p_cn_scb)
+ {
+ bta_ag_codec_negotiate(p_cn_scb);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_is_open
+**
+** Description Check if sco is open for this scb.
+**
+**
+** Returns TRUE if sco open for this scb, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_ag_sco_is_open(tBTA_AG_SCB *p_scb)
+{
+ return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
+ (bta_ag_cb.sco.p_curr_scb == p_scb));
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_is_opening
+**
+** Description Check if sco is in Opening state.
+**
+**
+** Returns TRUE if sco is in Opening state for this scb, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb)
+{
+#if (BTM_WBS_INCLUDED == TRUE )
+ return (((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) ||
+ (bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST)) &&
+ (bta_ag_cb.sco.p_curr_scb == p_scb));
+#else
+ return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
+ (bta_ag_cb.sco.p_curr_scb == p_scb));
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_listen
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_open
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ UINT8 event;
+
+ /* if another scb using sco, this is a transfer */
+ if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb)
+ {
+ event = BTA_AG_SCO_XFER_E;
+ }
+ /* else it is an open */
+ else
+ {
+ event = BTA_AG_SCO_OPEN_E;
+ }
+
+ bta_ag_sco_event(p_scb, event);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_close
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ /* if scb is in use */
+#if (BTM_WBS_INCLUDED == TRUE )
+ /* sco_idx is not allocated in SCO_CODEC_ST, we still need to move to listening state. */
+ if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) || (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST))
+#else
+ if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
+#endif
+ {
+ APPL_TRACE_DEBUG1("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
+ }
+}
+
+#if (BTM_WBS_INCLUDED == TRUE )
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_codec_nego
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result)
+{
+ if(result == TRUE)
+ {
+ /* Subsequent sco connection will skip codec negotiation */
+ p_scb->codec_updated = FALSE;
+
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
+ }
+ else /* codec negotiation failed */
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_shutdown
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_conn_open
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
+
+ bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_ON);
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ /* open SCO codec if SCO is routed through transport */
+ bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE, BTA_AG_CI_SCO_DATA_EVT);
+#endif
+
+ /* call app callback */
+ bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
+
+ p_scb->retry_with_sco_only = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_conn_close
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ UINT16 handle = bta_ag_scb_to_idx(p_scb);
+
+ /* clear current scb */
+ bta_ag_cb.sco.p_curr_scb = NULL;
+ p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+
+#if (BTM_WBS_INCLUDED == TRUE)
+ /* codec_fallback is set when AG is initiator and connection failed for mSBC. */
+ if (p_scb->codec_fallback && p_scb->svc_conn)
+ {
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
+ }
+ else if (p_scb->retry_with_sco_only && p_scb->svc_conn)
+ {
+ /* retry_with_sco_only is set when AG is initiator and connection failed for eSCO */
+ bta_ag_create_sco(p_scb, TRUE);
+ }
+#else
+ /* retry_with_sco_only, will be set only when AG is initiator
+ ** and AG is first trying to establish an eSCO connection */
+ if (p_scb->retry_with_sco_only && p_scb->svc_conn)
+ {
+ bta_ag_create_sco(p_scb, TRUE);
+ }
+#endif
+ else
+ {
+ /* Indicate if the closing of audio is because of transfer */
+ if (bta_ag_cb.sco.p_xfer_scb)
+ bta_ag_co_audio_state(handle, p_scb->app_id, BTA_AG_CO_AUD_STATE_OFF_XFER);
+ else
+ bta_ag_co_audio_state(handle, p_scb->app_id, BTA_AG_CO_AUD_STATE_OFF);
+
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
+
+ bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ /* if av got suspended by this call, let it resume. */
+ /* In case call stays alive regardless of sco, av should not be affected. */
+ if(((p_scb->call_ind == BTA_AG_CALL_INACTIVE) && (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
+ || (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END))
+ {
+ bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+ }
+
+ /* call app callback */
+ bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
+ }
+ p_scb->retry_with_sco_only = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sco_conn_rsp
+**
+** Description Process the SCO connection request
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
+{
+ tBTM_ESCO_PARAMS resp;
+ UINT8 hci_status = HCI_SUCCESS;
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ tBTA_CODEC_INFO codec_info = {BTA_SCO_CODEC_PCM};
+ UINT32 pcm_sample_rate;
+#endif
+
+ if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST ||
+ bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
+ bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST)
+ {
+ /* If script overrided sco parameter by BTA_CMD_SET_ESCO_PARAM */
+ if (bta_ag_cb.sco.param_updated)
+ {
+ resp = bta_ag_cb.sco.params;
+ }
+ else
+ {
+ resp.rx_bw = BTM_64KBITS_RATE;
+ resp.tx_bw = BTM_64KBITS_RATE;
+ resp.max_latency = 10;
+ resp.voice_contfmt = 0x60;
+ resp.retrans_effort = BTM_ESCO_RETRANS_POWER;
+
+ if (p_data->link_type == BTM_LINK_TYPE_SCO)
+ {
+ resp.packet_types = (BTM_SCO_LINK_ONLY_MASK |
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
+ }
+ else /* Allow controller to use all types available except 5-slot EDR */
+ {
+ resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
+ BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
+ BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
+ }
+ }
+
+ /* tell sys to stop av if any */
+ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+ /* Allow any platform specific pre-SCO set up to take place */
+ bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP);
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ /* When HS initiated SCO, it cannot be WBS. */
+ BTM_ConfigI2SPCM (BTM_SCO_CODEC_CVSD, (UINT8)HCI_BRCM_I2SPCM_IS_DEFAULT_ROLE, (UINT8)HCI_BRCM_I2SPCM_SAMPLE_DEFAULT, (UINT8)HCI_BRCM_I2SPCM_CLOCK_DEFAULT);
+#endif
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
+
+ /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
+ BTM_ConfigScoPath(bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id),
+ bta_ag_sco_read_cback, NULL, TRUE);
+#endif
+ }
+ else
+ hci_status = HCI_ERR_HOST_REJECT_DEVICE;
+
+#if (BTM_WBS_INCLUDED == TRUE )
+ /* If SCO open was initiated from HS, it must be CVSD */
+ p_scb->inuse_codec = BTA_AG_CODEC_NONE;
+#endif
+
+ BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_ci_sco_data
+**
+** Description Process the SCO data ready callin event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+ bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_set_esco_param
+**
+** Description Update esco parameters from script wrapper.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param)
+{
+ if(set_reset == FALSE) /* reset the parameters to default */
+ {
+ bta_ag_cb.sco.param_updated = FALSE;
+ APPL_TRACE_DEBUG0("bta_ag_set_esco_param : Resetting ESCO parameters to default");
+ }
+ else
+ {
+ bta_ag_cb.sco.param_updated = TRUE;
+ bta_ag_cb.sco.params = *param;
+ APPL_TRACE_DEBUG0("bta_ag_set_esco_param : Setting ESCO parameters");
+ }
+}
+
+/*******************************************************************************
+** Debugging functions
+*******************************************************************************/
+
+#if BTA_AG_SCO_DEBUG == TRUE
+static char *bta_ag_sco_evt_str(UINT8 event)
+{
+ switch (event)
+ {
+ case BTA_AG_SCO_LISTEN_E:
+ return "Listen Request";
+ case BTA_AG_SCO_OPEN_E:
+ return "Open Request";
+ case BTA_AG_SCO_XFER_E:
+ return "Transfer Request";
+#if (BTM_WBS_INCLUDED == TRUE )
+ case BTA_AG_SCO_CN_DONE_E:
+ return "Codec Negotiation Done";
+ case BTA_AG_SCO_REOPEN_E:
+ return "Reopen Request";
+#endif
+ case BTA_AG_SCO_CLOSE_E:
+ return "Close Request";
+ case BTA_AG_SCO_SHUTDOWN_E:
+ return "Shutdown Request";
+ case BTA_AG_SCO_CONN_OPEN_E:
+ return "Opened";
+ case BTA_AG_SCO_CONN_CLOSE_E:
+ return "Closed";
+ case BTA_AG_SCO_CI_DATA_E :
+ return "Sco Data";
+ default:
+ return "Unknown SCO Event";
+ }
+}
+
+static char *bta_ag_sco_state_str(UINT8 state)
+{
+ switch (state)
+ {
+ case BTA_AG_SCO_SHUTDOWN_ST:
+ return "Shutdown";
+ case BTA_AG_SCO_LISTEN_ST:
+ return "Listening";
+#if (BTM_WBS_INCLUDED == TRUE )
+ case BTA_AG_SCO_CODEC_ST:
+ return "Codec Negotiation";
+#endif
+ case BTA_AG_SCO_OPENING_ST:
+ return "Opening";
+ case BTA_AG_SCO_OPEN_CL_ST:
+ return "Open while closing";
+ case BTA_AG_SCO_OPEN_XFER_ST:
+ return "Opening while Transferring";
+ case BTA_AG_SCO_OPEN_ST:
+ return "Open";
+ case BTA_AG_SCO_CLOSING_ST:
+ return "Closing";
+ case BTA_AG_SCO_CLOSE_OP_ST:
+ return "Close while Opening";
+ case BTA_AG_SCO_CLOSE_XFER_ST:
+ return "Close while Transferring";
+ case BTA_AG_SCO_SHUTTING_ST:
+ return "Shutting Down";
+ default:
+ return "Unknown SCO State";
+ }
+}
+
+#endif
diff --git a/bta/ag/bta_ag_sdp.c b/bta/ag/bta_ag_sdp.c
new file mode 100644
index 0000000..d708cf2
--- /dev/null
+++ b/bta/ag/bta_ag_sdp.c
@@ -0,0 +1,500 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the audio gateway functions performing SDP
+ * operations.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "sdp_api.h"
+#include "btm_api.h"
+#include "gki.h"
+
+/* Number of protocol elements in protocol element list. */
+#define BTA_AG_NUM_PROTO_ELEMS 2
+
+/* Number of elements in service class id list. */
+#define BTA_AG_NUM_SVC_ELEMS 2
+
+/* size of database for service discovery */
+#ifndef BTA_AG_DISC_BUF_SIZE
+#define BTA_AG_DISC_BUF_SIZE GKI_MAX_BUF_SIZE
+#endif
+
+/* declare sdp callback functions */
+void bta_ag_sdp_cback_1(UINT16 status);
+void bta_ag_sdp_cback_2(UINT16 status);
+void bta_ag_sdp_cback_3(UINT16 status);
+
+/* SDP callback function table */
+typedef tSDP_DISC_CMPL_CB *tBTA_AG_SDP_CBACK;
+const tBTA_AG_SDP_CBACK bta_ag_sdp_cback_tbl[] =
+{
+ bta_ag_sdp_cback_1,
+ bta_ag_sdp_cback_2,
+ bta_ag_sdp_cback_3
+};
+
+/*******************************************************************************
+**
+** Function bta_ag_sdp_cback
+**
+** Description SDP callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ag_sdp_cback(UINT16 status, UINT8 idx)
+{
+ tBTA_AG_DISC_RESULT *p_buf;
+ UINT16 event;
+ tBTA_AG_SCB *p_scb;
+
+ APPL_TRACE_DEBUG1("bta_ag_sdp_cback status:0x%x", status);
+
+ if ((p_scb = bta_ag_scb_by_idx(idx)) != NULL)
+ {
+ /* set event according to int/acp */
+ if (p_scb->role == BTA_AG_ACP)
+ {
+ event = BTA_AG_DISC_ACP_RES_EVT;
+ }
+ else
+ {
+ event = BTA_AG_DISC_INT_RES_EVT;
+ }
+
+ if ((p_buf = (tBTA_AG_DISC_RESULT *) GKI_getbuf(sizeof(tBTA_AG_DISC_RESULT))) != NULL)
+ {
+ p_buf->hdr.event = event;
+ p_buf->hdr.layer_specific = idx;
+ p_buf->status = status;
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sdp_cback_1 to 3
+**
+** Description SDP callback functions. Since there is no way to
+** distinguish scb from the callback we need separate
+** callbacks for each scb.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_sdp_cback_1(UINT16 status) {bta_ag_sdp_cback(status, 1);}
+void bta_ag_sdp_cback_2(UINT16 status) {bta_ag_sdp_cback(status, 2);}
+void bta_ag_sdp_cback_3(UINT16 status) {bta_ag_sdp_cback(status, 3);}
+
+/******************************************************************************
+**
+** Function bta_ag_add_record
+**
+** Description This function is called by a server application to add
+** HSP or HFP information to an SDP record. Prior to
+** calling this function the application must call
+** SDP_CreateRecord() to create an SDP record.
+**
+** Returns TRUE if function execution succeeded,
+** FALSE if function execution failed.
+**
+******************************************************************************/
+BOOLEAN bta_ag_add_record(UINT16 service_uuid, char *p_service_name, UINT8 scn,
+ tBTA_AG_FEAT features, UINT32 sdp_handle)
+{
+ tSDP_PROTOCOL_ELEM proto_elem_list[BTA_AG_NUM_PROTO_ELEMS];
+ UINT16 svc_class_id_list[BTA_AG_NUM_SVC_ELEMS];
+ UINT16 browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
+ UINT16 version;
+ UINT16 profile_uuid;
+ UINT8 network;
+ BOOLEAN result = TRUE;
+ BOOLEAN codec_supported = FALSE;
+ UINT8 buf[2];
+
+ APPL_TRACE_DEBUG1("bta_ag_add_record uuid: %x", service_uuid);
+
+ memset( proto_elem_list, 0 , BTA_AG_NUM_PROTO_ELEMS*sizeof(tSDP_PROTOCOL_ELEM));
+
+ /* add the protocol element sequence */
+ proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+ proto_elem_list[0].num_params = 0;
+ proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
+ proto_elem_list[1].num_params = 1;
+ proto_elem_list[1].params[0] = scn;
+ result &= SDP_AddProtocolList(sdp_handle, BTA_AG_NUM_PROTO_ELEMS, proto_elem_list);
+
+ /* add service class id list */
+ svc_class_id_list[0] = service_uuid;
+ svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO;
+ result &= SDP_AddServiceClassIdList(sdp_handle, BTA_AG_NUM_SVC_ELEMS, svc_class_id_list);
+
+ /* add profile descriptor list */
+ if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE)
+ {
+ profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
+ version = HFP_VERSION_1_6;
+ }
+ else
+ {
+ profile_uuid = UUID_SERVCLASS_HEADSET;
+ version = HSP_VERSION_1_2;
+ }
+ result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);
+
+ /* add service name */
+ if (p_service_name != NULL && p_service_name[0] != 0)
+ {
+ result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
+ (UINT32)(strlen(p_service_name)+1), (UINT8 *) p_service_name);
+ }
+
+ /* add features and network */
+ if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE)
+ {
+ network = (features & BTA_AG_FEAT_REJECT) ? 1 : 0;
+ result &= SDP_AddAttribute(sdp_handle, ATTR_ID_DATA_STORES_OR_NETWORK,
+ UINT_DESC_TYPE, 1, &network);
+
+ if (features & BTA_AG_FEAT_CODEC)
+ codec_supported = TRUE;
+
+ features &= BTA_AG_SDP_FEAT_SPEC;
+
+ /* Codec bit position is different in SDP and in BRSF */
+ if (codec_supported)
+ features |= 0x0020;
+
+ UINT16_TO_BE_FIELD(buf, features);
+ result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, 2, buf);
+ }
+
+ /* add browse group list */
+ result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_create_records
+**
+** Description Create SDP records for registered services.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_create_records(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ int i;
+ tBTA_SERVICE_MASK services;
+
+ services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
+ for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1)
+ {
+ /* if service is set in mask */
+ if (services & 1)
+ {
+ /* add sdp record if not already registered */
+ if (bta_ag_cb.profile[i].sdp_handle == 0)
+ {
+ bta_ag_cb.profile[i].sdp_handle = SDP_CreateRecord();
+ bta_ag_cb.profile[i].scn = BTM_AllocateSCN();
+ bta_ag_add_record(bta_ag_uuid[i], p_data->api_register.p_name[i],
+ bta_ag_cb.profile[i].scn, p_data->api_register.features,
+ bta_ag_cb.profile[i].sdp_handle);
+ bta_sys_add_uuid(bta_ag_uuid[i]);
+ }
+ }
+ }
+
+ p_scb->hsp_version = HSP_VERSION_1_2;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_del_records
+**
+** Description Delete SDP records for any registered services.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_del_records(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ tBTA_AG_SCB *p = &bta_ag_cb.scb[0];
+ tBTA_SERVICE_MASK services;
+ tBTA_SERVICE_MASK others = 0;
+ int i;
+
+ /* get services of all other registered servers */
+ for (i = 0; i < BTA_AG_NUM_IDX; i++, p++)
+ {
+ if (p_scb == p)
+ {
+ continue;
+ }
+
+ if (p->in_use && p->dealloc == FALSE)
+ {
+ others |= p->reg_services;
+ }
+ }
+
+ others >>= BTA_HSP_SERVICE_ID;
+ services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
+ for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1, others >>= 1)
+ {
+ /* if service registered for this scb and not registered for any other scb */
+ if (((services & 1) == 1) && ((others & 1) == 0))
+ {
+ APPL_TRACE_DEBUG1("bta_ag_del_records %d", i);
+ if (bta_ag_cb.profile[i].sdp_handle != 0)
+ {
+ SDP_DeleteRecord(bta_ag_cb.profile[i].sdp_handle);
+ bta_ag_cb.profile[i].sdp_handle = 0;
+ }
+ BTM_FreeSCN(bta_ag_cb.profile[i].scn);
+ BTM_SecClrService(bta_ag_sec_id[i]);
+ bta_sys_remove_uuid(bta_ag_uuid[i]);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_sdp_find_attr
+**
+** Description Process SDP discovery results to find requested attributes
+** for requested service.
+**
+**
+** Returns TRUE if results found, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_ag_sdp_find_attr(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service)
+{
+ tSDP_DISC_REC *p_rec = NULL;
+ tSDP_DISC_ATTR *p_attr;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT16 uuid;
+ BOOLEAN result = FALSE;
+
+ if (service & BTA_HFP_SERVICE_MASK)
+ {
+ uuid = UUID_SERVCLASS_HF_HANDSFREE;
+ p_scb->peer_version = HFP_VERSION_1_1; /* Default version */
+ }
+ else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT)
+ {
+ uuid = UUID_SERVCLASS_HEADSET_HS;
+ p_scb->peer_version = 0x0100; /* Default version */
+ }
+ else
+ {
+ return result;
+ }
+
+ /* loop through all records we found */
+ while (TRUE)
+ {
+ /* get next record; if none found, we're done */
+ if ((p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec)) == NULL)
+ {
+ if (uuid == UUID_SERVCLASS_HEADSET_HS)
+ {
+ /* Search again in case the peer device is HSP v1.0 */
+ uuid = UUID_SERVCLASS_HEADSET;
+ if ((p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec)) == NULL)
+ {
+ break;
+ }
+ }
+ else
+ break;
+ }
+
+ /* get scn from proto desc list if initiator */
+ if (p_scb->role == BTA_AG_INT)
+ {
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ p_scb->peer_scn = (UINT8) pe.params[0];
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ /* get profile version (if failure, version parameter is not updated) */
+ SDP_FindProfileVersionInRec(p_rec, uuid, &p_scb->peer_version);
+
+ /* get features if HFP */
+ if (service & BTA_HFP_SERVICE_MASK)
+ {
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES)) != NULL)
+ {
+ /* Found attribute. Get value. */
+ /* There might be race condition between SDP and BRSF. */
+ /* Do not update if we already received BRSF. */
+ if (p_scb->peer_features == 0)
+ p_scb->peer_features = p_attr->attr_value.v.u16;
+ }
+ }
+ else /* HSP */
+ {
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL)) != NULL)
+ {
+ /* Remote volume control of HSP */
+ if (p_attr->attr_value.v.u8)
+ p_scb->peer_features |= BTA_AG_PEER_FEAT_VOL;
+ else
+ p_scb->peer_features &= ~BTA_AG_PEER_FEAT_VOL;
+ }
+
+ }
+
+ /* found what we needed */
+ result = TRUE;
+ break;
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_do_disc
+**
+** Description Do service discovery.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_do_disc(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service)
+{
+ tSDP_UUID uuid_list[2];
+ UINT16 num_uuid = 1;
+ UINT16 attr_list[4];
+ UINT8 num_attr;
+ BOOLEAN db_inited = FALSE;
+
+ /* HFP initiator; get proto list and features */
+ if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_INT)
+ {
+ attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+ attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+ attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
+ attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
+ num_attr = 4;
+ uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE;
+ }
+ /* HFP acceptor; get features */
+ else if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_ACP)
+ {
+ attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+ attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
+ attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
+ num_attr = 3;
+ uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE;
+ }
+ /* HSP initiator; get proto list */
+ else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT)
+ {
+ attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+ attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+ attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
+ attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
+ num_attr = 4;
+
+ uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HEADSET; /* Legacy from HSP v1.0 */
+ if (p_scb->hsp_version >= HSP_VERSION_1_2)
+ {
+ uuid_list[1].uu.uuid16 = UUID_SERVCLASS_HEADSET_HS;
+ num_uuid = 2;
+ }
+ }
+ /* HSP acceptor; no discovery */
+ else
+ {
+ return;
+ }
+
+ /* allocate buffer for sdp database */
+ p_scb->p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_AG_DISC_BUF_SIZE);
+
+ if(p_scb->p_disc_db)
+ {
+ /* set up service discovery database; attr happens to be attr_list len */
+ uuid_list[0].len = LEN_UUID_16;
+ uuid_list[1].len = LEN_UUID_16;
+ db_inited = SDP_InitDiscoveryDb(p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE, num_uuid,
+ uuid_list, num_attr, attr_list);
+ }
+
+ if(db_inited)
+ {
+ /*Service discovery not initiated */
+ db_inited = SDP_ServiceSearchAttributeRequest(p_scb->peer_addr, p_scb->p_disc_db,
+ bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
+ }
+
+ if(!db_inited)
+ {
+ /*free discover db */
+ bta_ag_free_db(p_scb, NULL);
+ /* sent failed event */
+ bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, NULL);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_free_db
+**
+** Description Free discovery database.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_free_db(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+ if (p_scb->p_disc_db != NULL)
+ {
+ GKI_freebuf(p_scb->p_disc_db);
+ p_scb->p_disc_db = NULL;
+ }
+}
diff --git a/bta/ar/bta_ar.c b/bta/ar/bta_ar.c
new file mode 100644
index 0000000..89b732a
--- /dev/null
+++ b/bta/ar/bta_ar.c
@@ -0,0 +1,348 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2008-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation for the audio/video registration module.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_ar_api.h"
+#include "bta_ar_int.h"
+
+
+/* AV control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_AR_CB bta_ar_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ar_id
+**
+** Description This function maps sys_id to ar id mask.
+**
+** Returns void
+**
+*******************************************************************************/
+static UINT8 bta_ar_id(tBTA_SYS_ID sys_id)
+{
+ UINT8 mask = 0;
+ if (sys_id == BTA_ID_AV)
+ {
+ mask = BTA_AR_AV_MASK;
+ }
+ else if (sys_id == BTA_ID_AVK)
+ {
+ mask = BTA_AR_AVK_MASK;
+ }
+
+ return mask;
+}
+
+/*******************************************************************************
+**
+** Function bta_ar_init
+**
+** Description This function is called to register to AVDTP.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ar_init(void)
+{
+ /* initialize control block */
+ memset(&bta_ar_cb, 0, sizeof(tBTA_AR_CB));
+}
+
+/*******************************************************************************
+**
+** Function bta_ar_reg_avdt
+**
+** Description This function is called to register to AVDTP.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ar_avdt_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+ /* route the AVDT registration callback to av or avk */
+ if (bta_ar_cb.p_av_conn_cback)
+ (*bta_ar_cb.p_av_conn_cback)(handle, bd_addr, event, p_data);
+ if (bta_ar_cb.p_avk_conn_cback)
+ (*bta_ar_cb.p_avk_conn_cback)(handle, bd_addr, event, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ar_reg_avdt
+**
+** Description AR module registration to AVDT.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ar_reg_avdt(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback, tBTA_SYS_ID sys_id)
+{
+ UINT8 mask = 0;
+
+ if (sys_id == BTA_ID_AV)
+ {
+ bta_ar_cb.p_av_conn_cback = p_cback;
+ mask = BTA_AR_AV_MASK;
+ }
+ else if (sys_id == BTA_ID_AVK)
+ {
+ bta_ar_cb.p_avk_conn_cback = p_cback;
+ mask = BTA_AR_AVK_MASK;
+ }
+#if (BTA_AR_DEBUG == TRUE)
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ar_reg_avdt: the registration is from wrong sys_id:%d", sys_id);
+ }
+#endif
+
+ if (mask)
+ {
+ if (bta_ar_cb.avdt_registered == 0)
+ {
+ AVDT_Register(p_reg, bta_ar_avdt_cback);
+ }
+ bta_ar_cb.avdt_registered |= mask;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ar_dereg_avdt
+**
+** Description This function is called to de-register from AVDTP.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ar_dereg_avdt(tBTA_SYS_ID sys_id)
+{
+ UINT8 mask = 0;
+
+ if (sys_id == BTA_ID_AV)
+ {
+ bta_ar_cb.p_av_conn_cback = NULL;
+ mask = BTA_AR_AV_MASK;
+ }
+ else if (sys_id == BTA_ID_AVK)
+ {
+ bta_ar_cb.p_avk_conn_cback = NULL;
+ mask = BTA_AR_AVK_MASK;
+ }
+ bta_ar_cb.avdt_registered &= ~mask;
+
+ if (bta_ar_cb.avdt_registered == 0)
+ AVDT_Deregister();
+}
+
+/*******************************************************************************
+**
+** Function bta_ar_avdt_conn
+**
+** Description This function is called to let ar know that some AVDTP profile
+** is connected for this sys_id.
+** If the other sys modules started a timer for PENDING_EVT,
+** the timer can be stopped now.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, BD_ADDR bd_addr)
+{
+ UINT8 event = BTA_AR_AVDT_CONN_EVT;
+ tAVDT_CTRL data;
+
+ if (sys_id == BTA_ID_AV)
+ {
+ if (bta_ar_cb.p_avk_conn_cback)
+ {
+ (*bta_ar_cb.p_avk_conn_cback)(0, bd_addr, event, &data);
+ }
+ }
+ else if (sys_id == BTA_ID_AVK)
+ {
+ if (bta_ar_cb.p_av_conn_cback)
+ {
+ (*bta_ar_cb.p_av_conn_cback)(0, bd_addr, event, &data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ar_reg_avct
+**
+** Description This function is called to register to AVCTP.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ar_reg_avct(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask, tBTA_SYS_ID sys_id)
+{
+ UINT8 mask = bta_ar_id (sys_id);
+
+ if (mask)
+ {
+ if (bta_ar_cb.avct_registered == 0)
+ {
+ AVCT_Register(mtu, mtu_br, sec_mask);
+ }
+ bta_ar_cb.avct_registered |= mask;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ar_dereg_avct
+**
+** Description This function is called to deregister from AVCTP.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ar_dereg_avct(tBTA_SYS_ID sys_id)
+{
+ UINT8 mask = bta_ar_id (sys_id);
+
+ bta_ar_cb.avct_registered &= ~mask;
+
+ if (bta_ar_cb.avct_registered == 0)
+ AVCT_Deregister();
+}
+
+/******************************************************************************
+**
+** Function bta_ar_reg_avrc
+**
+** Description This function is called to register an SDP record for AVRCP.
+**
+** Returns void
+**
+******************************************************************************/
+void bta_ar_reg_avrc(UINT16 service_uuid, char *service_name, char *provider_name,
+ UINT16 categories, tBTA_SYS_ID sys_id)
+{
+ UINT8 mask = bta_ar_id (sys_id);
+ UINT8 temp[8], *p;
+
+ if (!mask || !categories)
+ return;
+
+ if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET)
+ {
+ if (bta_ar_cb.sdp_tg_handle == 0)
+ {
+ bta_ar_cb.tg_registered = mask;
+ bta_ar_cb.sdp_tg_handle = SDP_CreateRecord();
+ AVRC_AddRecord(service_uuid, service_name, provider_name, categories, bta_ar_cb.sdp_tg_handle);
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+ bta_sys_add_uuid(service_uuid);
+#endif
+ }
+ /* only one TG is allowed (first-come, first-served).
+ * If sdp_tg_handle is non-0, ignore this request */
+ }
+ else if ((service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL) || (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_CONTROL))
+ {
+ bta_ar_cb.ct_categories [mask - 1] = categories;
+ categories = bta_ar_cb.ct_categories[0]|bta_ar_cb.ct_categories[1];
+ if (bta_ar_cb.sdp_ct_handle == 0)
+ {
+ bta_ar_cb.sdp_ct_handle = SDP_CreateRecord();
+ AVRC_AddRecord(service_uuid, service_name, provider_name, categories, bta_ar_cb.sdp_ct_handle);
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+ bta_sys_add_uuid(service_uuid);
+#endif
+ }
+ else
+ {
+ /* multiple CTs are allowed.
+ * Change supported categories on the second one */
+ p = temp;
+ UINT16_TO_BE_STREAM(p, categories);
+ SDP_AddAttribute(bta_ar_cb.sdp_ct_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
+ (UINT32)2, (UINT8*)temp);
+ }
+ }
+}
+
+/******************************************************************************
+**
+** Function bta_ar_dereg_avrc
+**
+** Description This function is called to de-register/delete an SDP record for AVRCP.
+**
+** Returns void
+**
+******************************************************************************/
+void bta_ar_dereg_avrc(UINT16 service_uuid, tBTA_SYS_ID sys_id)
+{
+ UINT8 mask = bta_ar_id (sys_id);
+ UINT16 categories = 0;
+ UINT8 temp[8], *p;
+
+ if (!mask)
+ return;
+
+ if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET)
+ {
+ if (bta_ar_cb.sdp_tg_handle && mask == bta_ar_cb.tg_registered)
+ {
+ bta_ar_cb.tg_registered = 0;
+ SDP_DeleteRecord(bta_ar_cb.sdp_tg_handle);
+ bta_ar_cb.sdp_tg_handle = 0;
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+ bta_sys_remove_uuid(service_uuid);
+#endif
+ }
+ }
+ else if (service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL)
+ {
+ if (bta_ar_cb.sdp_ct_handle)
+ {
+ bta_ar_cb.ct_categories [mask - 1] = 0;
+ categories = bta_ar_cb.ct_categories[0]|bta_ar_cb.ct_categories[1];
+ if (!categories)
+ {
+ /* no CT is still registered - cleaup */
+ SDP_DeleteRecord(bta_ar_cb.sdp_ct_handle);
+ bta_ar_cb.sdp_ct_handle = 0;
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+ bta_sys_remove_uuid(service_uuid);
+#endif
+ }
+ else
+ {
+ /* change supported categories to the remaning one */
+ p = temp;
+ UINT16_TO_BE_STREAM(p, categories);
+ SDP_AddAttribute(bta_ar_cb.sdp_ct_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
+ (UINT32)2, (UINT8*)temp);
+ }
+ }
+ }
+
+}
diff --git a/bta/ar/bta_ar_int.h b/bta/ar/bta_ar_int.h
new file mode 100644
index 0000000..d230448
--- /dev/null
+++ b/bta/ar/bta_ar_int.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2008-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private interface file for the BTA audio/video registration
+ * module.
+ *
+ ******************************************************************************/
+#ifndef BTA_AR_INT_H
+#define BTA_AR_INT_H
+
+#include "bta_av_api.h"
+
+
+#ifndef BTA_AR_DEBUG
+#define BTA_AR_DEBUG FALSE
+#endif
+
+#define BTA_AR_AV_MASK 0x01
+#define BTA_AR_AVK_MASK 0x02
+
+/* data associated with BTA_AR */
+typedef struct
+{
+ tAVDT_CTRL_CBACK *p_av_conn_cback; /* av connection callback function */
+ tAVDT_CTRL_CBACK *p_avk_conn_cback; /* avk connection callback function */
+ UINT8 avdt_registered;
+ UINT8 avct_registered;
+ UINT32 sdp_tg_handle;
+ UINT32 sdp_ct_handle;
+ UINT16 ct_categories[2];
+ UINT8 tg_registered;
+ tBTA_AV_HNDL hndl; /* Handle associated with the stream that rejected the connection. */
+} tBTA_AR_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* control block declaration */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_AR_CB bta_ar_cb;
+#else
+extern tBTA_AR_CB *bta_ar_cb_ptr;
+#define bta_ar_cb (*bta_ar_cb_ptr)
+#endif
+
+#endif /* BTA_AR_INT_H */
diff --git a/bta/av/bta_av_aact.c b/bta/av/bta_av_aact.c
new file mode 100644
index 0000000..741a5a0
--- /dev/null
+++ b/bta/av/bta_av_aact.c
@@ -0,0 +1,2733 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains action functions for advanced audio/video stream
+ * state machine. these functions are shared by both audio and video
+ * streams.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_av_int.h"
+#include "avdt_api.h"
+#include "bd.h"
+#include "utl.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/* the delay time in milliseconds to start service discovery on AVRCP */
+#ifndef BTA_AV_RC_DISC_TIME_VAL
+#define BTA_AV_RC_DISC_TIME_VAL 3500
+#endif
+
+/* the timer in milliseconds to guard against link busy and AVDT_CloseReq failed to be sent */
+#ifndef BTA_AV_CLOSE_REQ_TIME_VAL
+#define BTA_AV_CLOSE_REQ_TIME_VAL 4000
+#endif
+
+/* number to retry on reconfigure failure - some headsets requirs this number to be more than 1 */
+#ifndef BTA_AV_RECONFIG_RETRY
+#define BTA_AV_RECONFIG_RETRY 6
+#endif
+
+/* state machine states */
+enum
+{
+ BTA_AV_INIT_SST,
+ BTA_AV_INCOMING_SST,
+ BTA_AV_OPENING_SST,
+ BTA_AV_OPEN_SST,
+ BTA_AV_RCFG_SST,
+ BTA_AV_CLOSING_SST
+};
+
+
+/* the call out functions for audio stream */
+const tBTA_AV_CO_FUNCTS bta_av_a2d_cos =
+{
+ bta_av_co_audio_init,
+ bta_av_co_audio_disc_res,
+ bta_av_co_audio_getconfig,
+ bta_av_co_audio_setconfig,
+ bta_av_co_audio_open,
+ bta_av_co_audio_close,
+ bta_av_co_audio_start,
+ bta_av_co_audio_stop,
+ bta_av_co_audio_src_data_path,
+ bta_av_co_audio_delay
+};
+
+/* ssm action functions for audio stream */
+const tBTA_AV_SACT bta_av_a2d_action[] =
+{
+ bta_av_do_disc_a2d, /* BTA_AV_DO_DISC */
+ bta_av_cleanup, /* BTA_AV_CLEANUP */
+ bta_av_free_sdb, /* BTA_AV_FREE_SDB */
+ bta_av_config_ind, /* BTA_AV_CONFIG_IND */
+ bta_av_disconnect_req, /* BTA_AV_DISCONNECT_REQ */
+ bta_av_security_req, /* BTA_AV_SECURITY_REQ */
+ bta_av_security_rsp, /* BTA_AV_SECURITY_RSP */
+ bta_av_setconfig_rsp, /* BTA_AV_SETCONFIG_RSP */
+ bta_av_st_rc_timer, /* BTA_AV_ST_RC_TIMER */
+ bta_av_str_opened, /* BTA_AV_STR_OPENED */
+ bta_av_security_ind, /* BTA_AV_SECURITY_IND */
+ bta_av_security_cfm, /* BTA_AV_SECURITY_CFM */
+ bta_av_do_close, /* BTA_AV_DO_CLOSE */
+ bta_av_connect_req, /* BTA_AV_CONNECT_REQ */
+ bta_av_sdp_failed, /* BTA_AV_SDP_FAILED */
+ bta_av_disc_results, /* BTA_AV_DISC_RESULTS */
+ bta_av_disc_res_as_acp, /* BTA_AV_DISC_RES_AS_ACP */
+ bta_av_open_failed, /* BTA_AV_OPEN_FAILED */
+ bta_av_getcap_results, /* BTA_AV_GETCAP_RESULTS */
+ bta_av_setconfig_rej, /* BTA_AV_SETCONFIG_REJ */
+ bta_av_discover_req, /* BTA_AV_DISCOVER_REQ */
+ bta_av_conn_failed, /* BTA_AV_CONN_FAILED */
+ bta_av_do_start, /* BTA_AV_DO_START */
+ bta_av_str_stopped, /* BTA_AV_STR_STOPPED */
+ bta_av_reconfig, /* BTA_AV_RECONFIG */
+ bta_av_data_path, /* BTA_AV_DATA_PATH */
+ bta_av_start_ok, /* BTA_AV_START_OK */
+ bta_av_start_failed, /* BTA_AV_START_FAILED */
+ bta_av_str_closed, /* BTA_AV_STR_CLOSED */
+ bta_av_clr_cong, /* BTA_AV_CLR_CONG */
+ bta_av_suspend_cfm, /* BTA_AV_SUSPEND_CFM */
+ bta_av_rcfg_str_ok, /* BTA_AV_RCFG_STR_OK */
+ bta_av_rcfg_failed, /* BTA_AV_RCFG_FAILED */
+ bta_av_rcfg_connect, /* BTA_AV_RCFG_CONNECT */
+ bta_av_rcfg_discntd, /* BTA_AV_RCFG_DISCNTD */
+ bta_av_suspend_cont, /* BTA_AV_SUSPEND_CONT */
+ bta_av_rcfg_cfm, /* BTA_AV_RCFG_CFM */
+ bta_av_rcfg_open, /* BTA_AV_RCFG_OPEN */
+ bta_av_security_rej, /* BTA_AV_SECURITY_REJ */
+ bta_av_open_rc, /* BTA_AV_OPEN_RC */
+ bta_av_chk_2nd_start, /* BTA_AV_CHK_2ND_START */
+ bta_av_save_caps, /* BTA_AV_SAVE_CAPS */
+ bta_av_set_use_rc, /* BTA_AV_SET_USE_RC */
+ bta_av_cco_close, /* BTA_AV_CCO_CLOSE */
+ bta_av_switch_role, /* BTA_AV_SWITCH_ROLE */
+ bta_av_role_res, /* BTA_AV_ROLE_RES */
+ bta_av_delay_co, /* BTA_AV_DELAY_CO */
+ bta_av_open_at_inc, /* BTA_AV_OPEN_AT_INC */
+ NULL
+};
+
+/* these tables translate AVDT events to SSM events */
+static const UINT16 bta_av_stream_evt_ok[] = {
+ BTA_AV_STR_DISC_OK_EVT, /* AVDT_DISCOVER_CFM_EVT */
+ BTA_AV_STR_GETCAP_OK_EVT, /* AVDT_GETCAP_CFM_EVT */
+ BTA_AV_STR_OPEN_OK_EVT, /* AVDT_OPEN_CFM_EVT */
+ BTA_AV_STR_OPEN_OK_EVT, /* AVDT_OPEN_IND_EVT */
+ BTA_AV_STR_CONFIG_IND_EVT, /* AVDT_CONFIG_IND_EVT */
+ BTA_AV_STR_START_OK_EVT, /* AVDT_START_CFM_EVT */
+ BTA_AV_STR_START_OK_EVT, /* AVDT_START_IND_EVT */
+ BTA_AV_STR_SUSPEND_CFM_EVT, /* AVDT_SUSPEND_CFM_EVT */
+ BTA_AV_STR_SUSPEND_CFM_EVT, /* AVDT_SUSPEND_IND_EVT */
+ BTA_AV_STR_CLOSE_EVT, /* AVDT_CLOSE_CFM_EVT */
+ BTA_AV_STR_CLOSE_EVT, /* AVDT_CLOSE_IND_EVT */
+ BTA_AV_STR_RECONFIG_CFM_EVT, /* AVDT_RECONFIG_CFM_EVT */
+ 0, /* AVDT_RECONFIG_IND_EVT */
+ BTA_AV_STR_SECURITY_CFM_EVT, /* AVDT_SECURITY_CFM_EVT */
+ BTA_AV_STR_SECURITY_IND_EVT, /* AVDT_SECURITY_IND_EVT */
+ BTA_AV_STR_WRITE_CFM_EVT, /* AVDT_WRITE_CFM_EVT */
+ BTA_AV_AVDT_CONNECT_EVT, /* AVDT_CONNECT_IND_EVT */
+ BTA_AV_AVDT_DISCONNECT_EVT, /* AVDT_DISCONNECT_IND_EVT */
+#if (AVDT_REPORTING == TRUE)
+ BTA_AV_AVDT_RPT_CONN_EVT, /* AVDT_REPORT_CONN_EVT */
+ BTA_AV_AVDT_RPT_CONN_EVT, /* AVDT_REPORT_DISCONN_EVT */
+#endif
+ BTA_AV_AVDT_DELAY_RPT_EVT, /* AVDT_DELAY_REPORT_EVT */
+ 0 /* AVDT_DELAY_REPORT_CFM_EVT */
+};
+
+static const UINT16 bta_av_stream_evt_fail[] = {
+ BTA_AV_STR_DISC_FAIL_EVT, /* AVDT_DISCOVER_CFM_EVT */
+ BTA_AV_STR_GETCAP_FAIL_EVT, /* AVDT_GETCAP_CFM_EVT */
+ BTA_AV_STR_OPEN_FAIL_EVT, /* AVDT_OPEN_CFM_EVT */
+ BTA_AV_STR_OPEN_OK_EVT, /* AVDT_OPEN_IND_EVT */
+ BTA_AV_STR_CONFIG_IND_EVT, /* AVDT_CONFIG_IND_EVT */
+ BTA_AV_STR_START_FAIL_EVT, /* AVDT_START_CFM_EVT */
+ BTA_AV_STR_START_OK_EVT, /* AVDT_START_IND_EVT */
+ BTA_AV_STR_SUSPEND_CFM_EVT, /* AVDT_SUSPEND_CFM_EVT */
+ BTA_AV_STR_SUSPEND_CFM_EVT, /* AVDT_SUSPEND_IND_EVT */
+ BTA_AV_STR_CLOSE_EVT, /* AVDT_CLOSE_CFM_EVT */
+ BTA_AV_STR_CLOSE_EVT, /* AVDT_CLOSE_IND_EVT */
+ BTA_AV_STR_RECONFIG_CFM_EVT, /* AVDT_RECONFIG_CFM_EVT */
+ 0, /* AVDT_RECONFIG_IND_EVT */
+ BTA_AV_STR_SECURITY_CFM_EVT, /* AVDT_SECURITY_CFM_EVT */
+ BTA_AV_STR_SECURITY_IND_EVT, /* AVDT_SECURITY_IND_EVT */
+ BTA_AV_STR_WRITE_CFM_EVT, /* AVDT_WRITE_CFM_EVT */
+ BTA_AV_AVDT_CONNECT_EVT, /* AVDT_CONNECT_IND_EVT */
+ BTA_AV_AVDT_DISCONNECT_EVT, /* AVDT_DISCONNECT_IND_EVT */
+#if (AVDT_REPORTING == TRUE)
+ BTA_AV_AVDT_RPT_CONN_EVT, /* AVDT_REPORT_CONN_EVT */
+ BTA_AV_AVDT_RPT_CONN_EVT, /* AVDT_REPORT_DISCONN_EVT */
+#endif
+ BTA_AV_AVDT_DELAY_RPT_EVT, /* AVDT_DELAY_REPORT_EVT */
+ 0 /* AVDT_DELAY_REPORT_CFM_EVT */
+};
+
+static void bta_av_stream0_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+static void bta_av_stream1_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#if BTA_AV_NUM_STRS > 2
+static void bta_av_stream2_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#endif
+#if BTA_AV_NUM_STRS > 3
+static void bta_av_stream3_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#endif
+#if BTA_AV_NUM_STRS > 4
+static void bta_av_stream4_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#endif
+#if BTA_AV_NUM_STRS > 5
+static void bta_av_stream5_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#endif
+/* the array of callback functions to receive events from AVDT control channel */
+tAVDT_CTRL_CBACK * const bta_av_dt_cback[] =
+{
+ bta_av_stream0_cback
+ ,bta_av_stream1_cback
+#if BTA_AV_NUM_STRS > 2
+ ,bta_av_stream2_cback
+#endif
+#if BTA_AV_NUM_STRS > 3
+ ,bta_av_stream3_cback
+#endif
+#if BTA_AV_NUM_STRS > 4
+ ,bta_av_stream4_cback
+#endif
+#if BTA_AV_NUM_STRS > 5
+ ,bta_av_stream5_cback
+#endif
+};
+
+/*******************************************************************************
+**
+** Function bta_av_save_addr
+**
+** Description copy the bd_addr and maybe reset the supported flags
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_save_addr(tBTA_AV_SCB *p_scb, const BD_ADDR b)
+{
+ APPL_TRACE_DEBUG2("bta_av_save_addr r:%d, s:%d",
+ p_scb->recfg_sup, p_scb->suspend_sup);
+ if(bdcmp(p_scb->peer_addr, b) != 0)
+ {
+ APPL_TRACE_ERROR0("reset flags");
+ /* a new addr, reset the supported flags */
+ p_scb->recfg_sup = TRUE;
+ p_scb->suspend_sup = TRUE;
+ }
+
+ /* do this copy anyway, just in case the first addr matches
+ * the control block one by accident */
+ bdcpy(p_scb->peer_addr, b);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_st_rc_timer
+**
+** Description start the AVRC timer if no RC connection & CT is supported &
+** RC is used or
+** as ACP (we do not really know if we want AVRC)
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_st_rc_timer(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+
+ APPL_TRACE_DEBUG2("bta_av_st_rc_timer rc_handle:%d, use_rc: %d",
+ p_scb->rc_handle, p_scb->use_rc);
+ /* for outgoing RC connection as INT/CT */
+ if( (p_scb->rc_handle == BTA_AV_RC_HANDLE_NONE) &&
+ /*(bta_av_cb.features & BTA_AV_FEAT_RCCT) &&*/
+ (p_scb->use_rc == TRUE || (p_scb->role & BTA_AV_ROLE_AD_ACP)) )
+ {
+ if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) == 0)
+ bta_sys_start_timer(&p_scb->timer, BTA_AV_AVRC_TIMER_EVT, BTA_AV_RC_DISC_TIME_VAL);
+ else
+ p_scb->wait |= BTA_AV_WAIT_CHECK_RC;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_av_next_getcap
+**
+** Description The function gets the capabilities of the next available
+** stream found in the discovery results.
+**
+** Returns TRUE if we sent request to AVDT, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_av_next_getcap(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ int i;
+ tAVDT_GETCAP_REQ *p_req;
+ BOOLEAN sent_cmd = FALSE;
+
+ for (i = p_scb->sep_info_idx; i < p_scb->num_seps; i++)
+ {
+ /* steam not in use, is a sink, and is the right media type (audio/video) */
+ if ((p_scb->sep_info[i].in_use == FALSE) &&
+ (p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
+ (p_scb->sep_info[i].media_type == p_scb->media_type))
+ {
+ p_scb->sep_info_idx = i;
+
+ /* we got a stream; get its capabilities */
+ if (p_scb->p_cap == NULL)
+ {
+ p_scb->p_cap = (tAVDT_CFG *) GKI_getbuf(sizeof(tAVDT_CFG));
+ }
+ if (p_scb->p_cap == NULL)
+ {
+ i = p_scb->num_seps;
+ break;
+ }
+ if (p_scb->avdt_version >= AVDT_VERSION_SYNC)
+ {
+ p_req = AVDT_GetAllCapReq;
+ }
+ else
+ {
+ p_req = AVDT_GetCapReq;
+ }
+ (*p_req)(p_scb->peer_addr,
+ p_scb->sep_info[i].seid,
+ p_scb->p_cap, bta_av_dt_cback[p_scb->hdi]);
+ sent_cmd = TRUE;
+ break;
+ }
+ }
+
+ /* if no streams available then stream open fails */
+ if (!sent_cmd)
+ {
+ bta_av_ssm_execute(p_scb, BTA_AV_STR_GETCAP_FAIL_EVT, p_data);
+ }
+
+ return sent_cmd;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_av_proc_stream_evt
+**
+** Description Utility function to compose stream events.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data, int index)
+{
+ tBTA_AV_STR_MSG *p_msg;
+ UINT16 sec_len = 0;
+ tBTA_AV_SCB *p_scb = bta_av_cb.p_scb[index];
+ int xx;
+
+ if (p_data)
+ {
+ if (event == AVDT_SECURITY_IND_EVT)
+ {
+ sec_len = (p_data->security_ind.len < BTA_AV_SECURITY_MAX_LEN) ?
+ p_data->security_ind.len : BTA_AV_SECURITY_MAX_LEN;
+ }
+ else if (event == AVDT_SECURITY_CFM_EVT && p_data->hdr.err_code == 0)
+ {
+ sec_len = (p_data->security_cfm.len < BTA_AV_SECURITY_MAX_LEN) ?
+ p_data->security_cfm.len : BTA_AV_SECURITY_MAX_LEN;
+ }
+ }
+
+ if (p_scb && (p_msg = (tBTA_AV_STR_MSG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_STR_MSG) + sec_len))) != NULL)
+ {
+
+ /* copy event data, bd addr, and handle to event message buffer */
+ p_msg->hdr.offset = 0;
+
+ if (bd_addr != NULL)
+ {
+ bdcpy(p_msg->bd_addr, bd_addr);
+ APPL_TRACE_DEBUG6(" bd_addr:%02x-%02x-%02x-%02x-%02x-%02x",
+ bd_addr[0], bd_addr[1],
+ bd_addr[2], bd_addr[3],
+ bd_addr[4], bd_addr[5]);
+ }
+
+ if (p_data != NULL)
+ {
+ memcpy(&p_msg->msg, p_data, sizeof (tAVDT_CTRL));
+ /* copy config params to event message buffer */
+ switch (event)
+ {
+ case AVDT_CONFIG_IND_EVT:
+ /* We might have 2 SEP signallings(A2DP + VDP) with one peer device on one L2CAP.
+ * If we already have a signalling connection with the bd_addr and the streaming
+ * SST is at INIT state, change it to INCOMING state to handle the signalling
+ * from the 2nd SEP. */
+ if ((bta_av_find_lcb(bd_addr, BTA_AV_LCB_FIND) != NULL) && (bta_av_is_scb_init(p_scb)))
+ {
+ bta_av_set_scb_sst_incoming (p_scb);
+
+ /* When ACP_CONNECT_EVT was received, we put first available scb to incoming state.
+ * Later when we receive AVDT_CONFIG_IND_EVT, we use a new p_scb and set its state to
+ * incoming which we do it above.
+ * We also have to set the old p_scb state to init to be used later */
+ for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+ {
+ if ((bta_av_cb.p_scb[xx]) && (xx != index))
+ {
+ if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST)
+ {
+ bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
+ bta_av_cb.p_scb[xx]->coll_mask = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ memcpy(&p_msg->cfg, p_data->config_ind.p_cfg, sizeof(tAVDT_CFG));
+ break;
+
+ case AVDT_SECURITY_IND_EVT:
+ p_msg->msg.security_ind.p_data = (UINT8 *) (p_msg + 1);
+ memcpy(p_msg->msg.security_ind.p_data, p_data->security_ind.p_data, sec_len);
+ break;
+
+ case AVDT_SECURITY_CFM_EVT:
+ p_msg->msg.security_cfm.p_data = (UINT8 *) (p_msg + 1);
+ if (p_data->hdr.err_code == 0)
+ {
+ memcpy(p_msg->msg.security_cfm.p_data, p_data->security_cfm.p_data, sec_len);
+ }
+ break;
+ case AVDT_SUSPEND_IND_EVT:
+ p_msg->msg.hdr.err_code = 0;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ p_msg->msg.hdr.err_code = 0;
+
+ /* look up application event */
+ if ((p_data == NULL) || (p_data->hdr.err_code == 0))
+ {
+ p_msg->hdr.event = bta_av_stream_evt_ok[event];
+ }
+ else
+ {
+ p_msg->hdr.event = bta_av_stream_evt_fail[event];
+ }
+
+ p_msg->initiator = FALSE;
+ if (event == AVDT_SUSPEND_CFM_EVT)
+ p_msg->initiator = TRUE;
+
+ APPL_TRACE_EVENT1("hndl:x%x", p_scb->hndl);
+ p_msg->hdr.layer_specific = p_scb->hndl;
+ p_msg->handle = handle;
+ p_msg->avdt_event = event;
+ bta_sys_sendmsg(p_msg);
+ }
+
+/* coverity[var_deref_model]: Variable "p_data" tracked as NULL was passed to function "bta_av_conn_cback" that dereferences it.
+ * false-positive: bta_av_conn_cback only processes AVDT_CONNECT_IND_EVT and AVDT_DISCONNECT_IND_EVT event
+ * these 2 events always have associated p_data
+ */
+ bta_av_conn_cback(handle, bd_addr, event, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_stream0_cback
+**
+** Description This is the AVDTP callback function for stream events.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_stream0_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+ APPL_TRACE_EVENT2("bta_av_stream0_cback avdt_handle: %d event=0x%x", handle, event);
+ bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_stream1_cback
+**
+** Description This is the AVDTP callback function for stream events.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_stream1_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+ APPL_TRACE_EVENT2("bta_av_stream1_cback avdt_handle: %d event=0x%x", handle, event);
+ bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 1);
+}
+
+#if BTA_AV_NUM_STRS > 2
+/*******************************************************************************
+**
+** Function bta_av_stream2_cback
+**
+** Description This is the AVDTP callback function for stream events.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_stream2_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+ APPL_TRACE_EVENT2("bta_av_stream2_cback avdt_handle: %d event=0x%x", handle, event);
+ bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 2);
+}
+#endif
+
+#if BTA_AV_NUM_STRS > 3
+/*******************************************************************************
+**
+** Function bta_av_stream3_cback
+**
+** Description This is the AVDTP callback function for stream events.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_stream3_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+ APPL_TRACE_EVENT2("bta_av_stream3_cback avdt_handle: %d event=0x%x", handle, event);
+ bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 3);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_av_stream4_cback
+**
+** Description This is the AVDTP callback function for stream events.
+**
+** Returns void
+**
+*******************************************************************************/
+#if BTA_AV_NUM_STRS > 4
+static void bta_av_stream4_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+ APPL_TRACE_EVENT2("bta_av_stream4_cback avdt_handle: %d event=0x%x", handle, event);
+ bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 4);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_av_stream5_cback
+**
+** Description This is the AVDTP callback function for stream events.
+**
+** Returns void
+**
+*******************************************************************************/
+#if BTA_AV_NUM_STRS > 5
+static void bta_av_stream5_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+ APPL_TRACE_EVENT2("bta_av_stream5_cback avdt_handle: %d event=0x%x", handle, event);
+ bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 5);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_av_a2d_sdp_cback
+**
+** Description A2DP service discovery callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_a2d_sdp_cback(BOOLEAN found, tA2D_Service *p_service)
+{
+ tBTA_AV_SDP_RES *p_msg;
+ tBTA_AV_SCB *p_scb;
+
+ if ((p_msg = (tBTA_AV_SDP_RES *) GKI_getbuf(sizeof(tBTA_AV_SDP_RES))) != NULL)
+ {
+ p_msg->hdr.event = (found) ? BTA_AV_SDP_DISC_OK_EVT : BTA_AV_SDP_DISC_FAIL_EVT;
+
+ p_scb = bta_av_hndl_to_scb(bta_av_cb.handle);
+ if (p_scb)
+ {
+ if (found && (p_service != NULL))
+ p_scb->avdt_version = p_service->avdt_version;
+ else
+ p_scb->avdt_version = 0x00;
+
+ p_msg->hdr.layer_specific = bta_av_cb.handle;
+ bta_sys_sendmsg(p_msg);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1 ("bta_av_a2d_sdp_cback, no scb found for handle(0x%x)", bta_av_cb.handle);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_adjust_seps_idx
+**
+** Description adjust the sep_idx
+**
+** Returns
+**
+*******************************************************************************/
+static void bta_av_adjust_seps_idx(tBTA_AV_SCB *p_scb)
+{
+ int xx;
+
+ APPL_TRACE_DEBUG1("bta_av_adjust_seps_idx codec_type: %d", p_scb->codec_type);
+ for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
+ {
+ APPL_TRACE_DEBUG2("av_handle: %d codec_type: %d",
+ p_scb->seps[xx].av_handle, p_scb->seps[xx].codec_type);
+ if(p_scb->seps[xx].av_handle && p_scb->codec_type == p_scb->seps[xx].codec_type)
+ {
+ p_scb->sep_idx = xx;
+ p_scb->avdt_handle = p_scb->seps[xx].av_handle;
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_switch_role
+**
+** Description Switch role was not started and a timer was started.
+** another attempt to switch role now - still opening.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_switch_role (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RS_RES switch_res = BTA_AV_RS_NONE;
+ tBTA_AV_API_OPEN *p_buf = &p_scb->q_info.open;
+
+ APPL_TRACE_DEBUG1("bta_av_switch_role wait:x%x", p_scb->wait);
+ if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_START)
+ p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RETRY;
+
+ /* clear the masks set when the timer is started */
+ p_scb->wait &= ~(BTA_AV_WAIT_ROLE_SW_RES_OPEN|BTA_AV_WAIT_ROLE_SW_RES_START);
+
+ if (p_scb->q_tag == BTA_AV_Q_TAG_OPEN)
+ {
+ if (bta_av_switch_if_needed(p_scb) || !bta_av_link_role_ok(p_scb, A2D_SET_MULTL_BIT))
+ {
+ p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_OPEN;
+ }
+ else
+ {
+ /* this should not happen in theory. Just in case...
+ * continue to do_disc_a2d */
+ switch_res = BTA_AV_RS_DONE;
+ }
+ }
+ else
+ {
+ /* report failure on OPEN */
+ switch_res = BTA_AV_RS_FAIL;
+ }
+
+ if (switch_res != BTA_AV_RS_NONE)
+ {
+ if (bta_av_cb.rs_idx == (p_scb->hdi + 1))
+ {
+ bta_av_cb.rs_idx = 0;
+ }
+ p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_RETRY;
+ p_scb->q_tag = 0;
+ p_buf->switch_res = switch_res;
+ bta_av_do_disc_a2d(p_scb, (tBTA_AV_DATA *)p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_role_res
+**
+** Description Handle the role changed event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ BOOLEAN initiator = FALSE;
+ tBTA_AV_START start;
+ tBTA_AV_OPEN av_open;
+
+ APPL_TRACE_DEBUG3("bta_av_role_res q_tag:%d, wait:x%x, role:x%x", p_scb->q_tag, p_scb->wait, p_scb->role);
+ if (p_scb->role & BTA_AV_ROLE_START_INT)
+ initiator = TRUE;
+
+ if (p_scb->q_tag == BTA_AV_Q_TAG_START)
+ {
+ if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_STARTED)
+ {
+ p_scb->role &= ~BTA_AV_ROLE_START_INT;
+ p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+ if (p_data->role_res.hci_status != HCI_SUCCESS)
+ {
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ /* start failed because of role switch. */
+ start.chnl = p_scb->chnl;
+ start.status = BTA_AV_FAIL_ROLE;
+ start.hndl = p_scb->hndl;
+ start.initiator = initiator;
+ (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+ }
+ else
+ {
+ bta_av_start_ok(p_scb, p_data);
+ }
+ }
+ else if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_START)
+ p_scb->wait |= BTA_AV_WAIT_ROLE_SW_FAILED;
+ }
+ else if (p_scb->q_tag == BTA_AV_Q_TAG_OPEN)
+ {
+ if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_OPEN)
+ {
+ p_scb->role &= ~BTA_AV_ROLE_START_INT;
+ p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+
+ if (p_data->role_res.hci_status != HCI_SUCCESS)
+ {
+ /* Open failed because of role switch. */
+ bdcpy(av_open.bd_addr, p_scb->peer_addr);
+ av_open.chnl = p_scb->chnl;
+ av_open.hndl = p_scb->hndl;
+ start.status = BTA_AV_FAIL_ROLE;
+ (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *)&av_open);
+ }
+ else
+ {
+ /* Continue av open process */
+ p_scb->q_info.open.switch_res = BTA_AV_RS_DONE;
+ bta_av_do_disc_a2d (p_scb, (tBTA_AV_DATA *)&(p_scb->q_info.open));
+ }
+ }
+ else
+ {
+ APPL_TRACE_WARNING2 ("Unexpected role switch event: q_tag = %d wait = %d", p_scb->q_tag, p_scb->wait);
+ }
+ }
+
+ APPL_TRACE_DEBUG2("wait:x%x, role:x%x", p_scb->wait, p_scb->role);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_delay_co
+**
+** Description Call the delay call-out function to report the delay report
+** from SNK
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_delay_co (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ p_scb->p_cos->delay(p_scb->hndl, p_data->str_msg.msg.delay_rpt_cmd.delay);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_do_disc_a2d
+**
+** Description Do service discovery for A2DP.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ BOOLEAN ok_continue = FALSE;
+ tA2D_SDP_DB_PARAMS db_params;
+ UINT16 attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
+ ATTR_ID_PROTOCOL_DESC_LIST,
+ ATTR_ID_BT_PROFILE_DESC_LIST};
+
+ APPL_TRACE_DEBUG3("bta_av_do_disc_a2d use_rc: %d rs:%d, oc:%d",
+ p_data->api_open.use_rc, p_data->api_open.switch_res, bta_av_cb.audio_open_cnt);
+
+ memcpy (&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
+
+ switch(p_data->api_open.switch_res)
+ {
+ case BTA_AV_RS_NONE:
+ if (bta_av_switch_if_needed(p_scb) || !bta_av_link_role_ok(p_scb, A2D_SET_MULTL_BIT))
+ {
+ /* waiting for role switch result. save the api to control block */
+ memcpy(&p_scb->q_info.open, &p_data->api_open, sizeof(tBTA_AV_API_OPEN));
+ p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_OPEN;
+ p_scb->q_tag = BTA_AV_Q_TAG_OPEN;
+ }
+ else
+ {
+ ok_continue = TRUE;
+ }
+ break;
+
+ case BTA_AV_RS_FAIL:
+ /* report a new failure event */
+ p_scb->open_status = BTA_AV_FAIL_ROLE;
+ bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_FAIL_EVT, NULL);
+ break;
+
+ case BTA_AV_RS_OK:
+ p_data = (tBTA_AV_DATA *)&p_scb->q_info.open;
+ /* continue to open if link role is ok */
+ if (bta_av_link_role_ok(p_scb, A2D_SET_MULTL_BIT))
+ {
+ ok_continue = TRUE;
+ }
+ else
+ {
+ p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_OPEN;
+ }
+ break;
+
+ case BTA_AV_RS_DONE:
+ ok_continue = TRUE;
+ break;
+ }
+
+ APPL_TRACE_DEBUG3("ok_continue: %d wait:x%x, q_tag: %d", ok_continue, p_scb->wait, p_scb->q_tag);
+ if (!ok_continue)
+ return;
+
+ /* clear the role switch bits */
+ p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+
+ if (p_scb->wait & BTA_AV_WAIT_CHECK_RC)
+ {
+ p_scb->wait &= ~BTA_AV_WAIT_CHECK_RC;
+ bta_sys_start_timer(&p_scb->timer, BTA_AV_AVRC_TIMER_EVT, BTA_AV_RC_DISC_TIME_VAL);
+ }
+
+ if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
+ {
+ L2CA_SetDesireRole(L2CAP_ROLE_DISALLOW_SWITCH);
+
+ if (bta_av_cb.audio_open_cnt == 1)
+ {
+ /* there's already an A2DP connection. do not allow switch */
+ bta_sys_clear_default_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH);
+ }
+ }
+ /* store peer addr other parameters */
+ bta_av_save_addr(p_scb, p_data->api_open.bd_addr);
+ p_scb->sec_mask = p_data->api_open.sec_mask;
+ p_scb->use_rc = p_data->api_open.use_rc;
+
+ bta_sys_app_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+
+ /* allocate discovery database */
+ if (p_scb->p_disc_db == NULL)
+ {
+ p_scb->p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_AV_DISC_BUF_SIZE);
+ }
+
+ /* only one A2D find service is active at a time */
+ bta_av_cb.handle = p_scb->hndl;
+
+ if(p_scb->p_disc_db)
+ {
+ /* set up parameters */
+ db_params.db_len = BTA_AV_DISC_BUF_SIZE;
+ db_params.num_attr = 3;
+ db_params.p_db = p_scb->p_disc_db;
+ db_params.p_attrs = attr_list;
+
+ if(A2D_FindService(UUID_SERVCLASS_AUDIO_SINK, p_scb->peer_addr, &db_params,
+ bta_av_a2d_sdp_cback) == A2D_SUCCESS)
+ {
+ return;
+ }
+ }
+
+ /* when the code reaches here, either the DB is NULL
+ * or A2D_FindService is not successful */
+ bta_av_a2d_sdp_cback(FALSE, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_cleanup
+**
+** Description cleanup AV stream control block.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_CONN_CHG msg;
+ int xx;
+ UINT8 role = BTA_AV_ROLE_AD_INT;
+
+ APPL_TRACE_DEBUG0("bta_av_cleanup");
+
+ /* free any buffers */
+ utl_freebuf((void **) &p_scb->p_cap);
+ utl_freebuf((void **) &p_scb->p_disc_db);
+ p_scb->avdt_version = 0;
+
+ /* initialize some control block variables */
+ p_scb->open_status = BTA_AV_SUCCESS;
+
+ /* if de-registering shut everything down */
+ msg.hdr.layer_specific = p_scb->hndl;
+ p_scb->started = FALSE;
+ p_scb->cong = FALSE;
+ p_scb->role = role;
+ p_scb->cur_psc_mask = 0;
+ p_scb->wait = 0;
+ p_scb->num_disc_snks = 0;
+ bta_sys_stop_timer(&p_scb->timer);
+ if (p_scb->deregistring)
+ {
+ /* remove stream */
+ for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
+ {
+ if(p_scb->seps[xx].av_handle)
+ AVDT_RemoveStream(p_scb->seps[xx].av_handle);
+ p_scb->seps[xx].av_handle = 0;
+ }
+
+ bta_av_dereg_comp((tBTA_AV_DATA *) &msg);
+ }
+ else
+ {
+ /* report stream closed to main SM */
+ msg.is_up = FALSE;
+ bdcpy(msg.peer_addr, p_scb->peer_addr);
+ bta_av_conn_chg((tBTA_AV_DATA *) &msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_free_sdb
+**
+** Description Free service discovery db buffer.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_free_sdb(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ utl_freebuf((void **) &p_scb->p_disc_db);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_config_ind
+**
+** Description Handle a stream configuration indication from the peer.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_CI_SETCONFIG setconfig;
+ tAVDT_SEP_INFO *p_info;
+ tAVDT_CFG *p_evt_cfg = &p_data->str_msg.cfg;
+ UINT8 psc_mask = (p_evt_cfg->psc_mask | p_scb->cfg.psc_mask);
+
+ p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
+ memcpy(p_scb->cfg.codec_info, p_evt_cfg->codec_info, AVDT_CODEC_SIZE);
+ p_scb->codec_type = p_evt_cfg->codec_info[BTA_AV_CODEC_TYPE_IDX];
+ bta_av_save_addr(p_scb, p_data->str_msg.bd_addr);
+
+ /* Clear collision mask */
+ p_scb->coll_mask = 0;
+ bta_sys_stop_timer(&bta_av_cb.acp_sig_tmr);
+
+ /* if no codec parameters in configuration, fail */
+ if ((p_evt_cfg->num_codec == 0) ||
+ /* or the peer requests for a service we do not support */
+ ((psc_mask != p_scb->cfg.psc_mask) &&
+ (psc_mask != (p_scb->cfg.psc_mask&~AVDT_PSC_DELAY_RPT))) )
+ {
+ setconfig.hndl = p_scb->hndl; /* we may not need this */
+ setconfig.err_code = AVDT_ERR_UNSUP_CFG;
+ bta_av_ssm_execute(p_scb, BTA_AV_CI_SETCONFIG_FAIL_EVT, (tBTA_AV_DATA *) &setconfig);
+ }
+ else
+ {
+ p_info = &p_scb->sep_info[0];
+ p_info->in_use = 0;
+ p_info->media_type = p_scb->media_type;
+ p_info->seid = p_data->str_msg.msg.config_ind.int_seid;
+ p_info->tsep = AVDT_TSEP_SNK;
+ p_scb->role |= BTA_AV_ROLE_AD_ACP;
+ p_scb->cur_psc_mask = p_evt_cfg->psc_mask;
+ if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
+ p_scb->use_rc = TRUE;
+ else
+ p_scb->use_rc = FALSE;
+
+ p_scb->num_seps = 1;
+ p_scb->sep_info_idx = 0;
+ APPL_TRACE_DEBUG3("bta_av_config_ind: SEID: %d use_rc: %d cur_psc_mask:0x%x", p_info->seid, p_scb->use_rc, p_scb->cur_psc_mask);
+
+ p_scb->p_cos->setcfg(p_scb->hndl, p_scb->codec_type,
+ p_evt_cfg->codec_info,
+ p_info->seid,
+ p_scb->peer_addr,
+ p_evt_cfg->num_protect,
+ p_evt_cfg->protect_info);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_disconnect_req
+**
+** Description Disconnect AVDTP connection.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_disconnect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RCB *p_rcb;
+ APPL_TRACE_DEBUG1("bta_av_disconnect_req conn_lcb: 0x%x", bta_av_cb.conn_lcb);
+
+ bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+ bta_sys_stop_timer(&p_scb->timer);
+ if(bta_av_cb.conn_lcb)
+ {
+ p_rcb = bta_av_get_rcb_by_shdl((UINT8)(p_scb->hdi + 1));
+ if (p_rcb)
+ bta_av_del_rc(p_rcb);
+ AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ }
+ else
+ {
+ bta_av_ssm_execute(p_scb, BTA_AV_AVDT_DISCONNECT_EVT, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_security_req
+**
+** Description Send an AVDTP security request.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_security_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ if (bta_av_cb.features & BTA_AV_FEAT_PROTECT)
+ {
+ AVDT_SecurityReq(p_scb->avdt_handle, p_data->api_protect_req.p_data,
+ p_data->api_protect_req.len);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_security_rsp
+**
+** Description Send an AVDTP security response.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_security_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ if (bta_av_cb.features & BTA_AV_FEAT_PROTECT)
+ {
+ AVDT_SecurityRsp(p_scb->avdt_handle, p_scb->avdt_label, p_data->api_protect_rsp.error_code,
+ p_data->api_protect_rsp.p_data, p_data->api_protect_rsp.len);
+ }
+ else
+ {
+ AVDT_SecurityRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_NSC,
+ NULL, 0);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_setconfig_rsp
+**
+** Description setconfig is OK
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ UINT8 num = p_data->ci_setconfig.num_seid + 1;
+ UINT8 *p_seid = p_data->ci_setconfig.p_seid;
+ int i;
+
+ /* we like this codec_type. find the sep_idx */
+ bta_av_adjust_seps_idx(p_scb);
+ APPL_TRACE_DEBUG2("bta_av_setconfig_rsp: sep_idx: %d cur_psc_mask:0x%x", p_scb->sep_idx, p_scb->cur_psc_mask);
+ AVDT_ConfigRsp(p_scb->avdt_handle, p_scb->avdt_label, p_data->ci_setconfig.err_code,
+ p_data->ci_setconfig.category);
+
+ bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+
+ if(p_data->ci_setconfig.err_code == AVDT_SUCCESS)
+ {
+ p_scb->wait = BTA_AV_WAIT_ACP_CAPS_ON;
+ if(p_data->ci_setconfig.recfg_needed)
+ p_scb->role |= BTA_AV_ROLE_SUSPEND_OPT;
+ APPL_TRACE_ERROR3("bta_av_setconfig_rsp recfg_needed:%d role:x%x num:%d",
+ p_data->ci_setconfig.recfg_needed, p_scb->role, num);
+ /* callout module tells BTA the number of "good" SEPs and their SEIDs.
+ * getcap on these SEID */
+ p_scb->num_seps = num;
+
+ if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT)
+ p_scb->avdt_version = AVDT_VERSION_SYNC;
+
+
+ if (p_scb->codec_type == BTA_AV_CODEC_SBC || num > 1)
+ {
+ /* if SBC is used by the SNK as INT, discover req is not sent in bta_av_config_ind.
+ * call disc_res now */
+ p_scb->p_cos->disc_res(p_scb->hndl, num, num, p_scb->peer_addr);
+ }
+ else
+ {
+ /* we do not know the peer device and it is using non-SBC codec
+ * we need to know all the SEPs on SNK */
+ bta_av_discover_req(p_scb, NULL);
+ return;
+ }
+
+ for (i = 1; i < num; i++)
+ {
+ APPL_TRACE_DEBUG2("sep_info[%d] SEID: %d", i, p_seid[i-1]);
+ /* initialize the sep_info[] to get capabilities */
+ p_scb->sep_info[i].in_use = FALSE;
+ p_scb->sep_info[i].tsep = AVDT_TSEP_SNK;
+ p_scb->sep_info[i].media_type = p_scb->media_type;
+ p_scb->sep_info[i].seid = p_seid[i-1];
+ }
+ bta_av_next_getcap(p_scb, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_str_opened
+**
+** Description Stream opened OK (incoming/outgoing).
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_CONN_CHG msg;
+ tBTA_AV_OPEN open;
+ UINT8 *p;
+ UINT16 mtu;
+
+ msg.hdr.layer_specific = p_scb->hndl;
+ msg.is_up = TRUE;
+ bdcpy(msg.peer_addr, p_scb->peer_addr);
+ p_scb->l2c_cid = AVDT_GetL2CapChannel(p_scb->avdt_handle);
+ bta_av_conn_chg((tBTA_AV_DATA *) &msg);
+ /* set the congestion flag, so AV would not send media packets by accident */
+ p_scb->cong = TRUE;
+
+
+ p_scb->stream_mtu = p_data->str_msg.msg.open_ind.peer_mtu - AVDT_MEDIA_HDR_SIZE;
+ mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
+ APPL_TRACE_DEBUG3("bta_av_str_opened l2c_cid: 0x%x stream_mtu: %d mtu: %d",
+ p_scb->l2c_cid, p_scb->stream_mtu, mtu);
+ if(mtu == 0 || mtu > p_scb->stream_mtu)
+ mtu = p_scb->stream_mtu;
+
+ /* Set the media channel as medium priority */
+ L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_MEDIUM);
+ L2CA_SetChnlFlushability (p_scb->l2c_cid, TRUE);
+
+ bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+ memset(&p_scb->q_info, 0, sizeof(tBTA_AV_Q_INFO));
+
+ p_scb->l2c_bufs = 0;
+ p_scb->p_cos->open(p_scb->hndl,
+ p_scb->codec_type, p_scb->cfg.codec_info, mtu);
+
+ {
+ /* TODO check if other audio channel is open.
+ * If yes, check if reconfig is needed
+ * Rigt now we do not do this kind of checking.
+ * BTA-AV is INT for 2nd audio connection.
+ * The application needs to make sure the current codec_info is proper.
+ * If one audio connection is open and another SNK attempts to connect to AV,
+ * the connection will be rejected.
+ */
+ /* check if other audio channel is started. If yes, start */
+ bdcpy(open.bd_addr, p_scb->peer_addr);
+ open.chnl = p_scb->chnl;
+ open.hndl = p_scb->hndl;
+ open.status = BTA_AV_SUCCESS;
+ open.starting = bta_av_chk_start(p_scb);
+ open.edr = 0;
+ if( NULL != (p = BTM_ReadRemoteFeatures(p_scb->peer_addr)))
+ {
+ if(HCI_EDR_ACL_2MPS_SUPPORTED(p))
+ open.edr |= BTA_AV_EDR_2MBPS;
+ if(HCI_EDR_ACL_3MPS_SUPPORTED(p))
+ open.edr |= BTA_AV_EDR_3MBPS;
+ }
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+ bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr);
+#endif
+ (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *) &open);
+ if(open.starting)
+ {
+ bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_security_ind
+**
+** Description Handle an AVDTP security indication.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_security_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_PROTECT_REQ protect_req;
+
+ p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
+
+ if (bta_av_cb.features & BTA_AV_FEAT_PROTECT)
+ {
+ protect_req.chnl = p_scb->chnl;
+ protect_req.hndl = p_scb->hndl;
+ /*
+ APPL_TRACE_EVENT1("sec ind handle: x%x", protect_req.hndl);
+ */
+ protect_req.p_data = p_data->str_msg.msg.security_ind.p_data;
+ protect_req.len = p_data->str_msg.msg.security_ind.len;
+
+ (*bta_av_cb.p_cback)(BTA_AV_PROTECT_REQ_EVT, (tBTA_AV *) &protect_req);
+ }
+ /* app doesn't support security indication; respond with failure */
+ else
+ {
+ AVDT_SecurityRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_NSC, NULL, 0);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_security_cfm
+**
+** Description Handle an AVDTP security confirm.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_security_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_PROTECT_RSP protect_rsp;
+
+ if (bta_av_cb.features & BTA_AV_FEAT_PROTECT)
+ {
+ protect_rsp.chnl = p_scb->chnl;
+ protect_rsp.hndl = p_scb->hndl;
+ protect_rsp.p_data = p_data->str_msg.msg.security_cfm.p_data;
+ protect_rsp.len = p_data->str_msg.msg.security_cfm.len;
+ protect_rsp.err_code= p_data->str_msg.msg.hdr.err_code;
+
+ (*bta_av_cb.p_cback)(BTA_AV_PROTECT_RSP_EVT, (tBTA_AV *) &protect_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_do_close
+**
+** Description Close stream.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_do_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ /* stop stream if started */
+ if (p_scb->co_started)
+ {
+ bta_av_str_stopped(p_scb, NULL);
+ }
+ bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+
+ /* close stream */
+ p_scb->started = FALSE;
+
+ /* drop the buffers queued in L2CAP */
+ L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+
+ AVDT_CloseReq(p_scb->avdt_handle);
+ /* just in case that the link is congested, link is flow controled by peer or
+ * for whatever reason the the close request can not be sent in time.
+ * when this timer expires, AVDT_DisconnectReq will be called to disconnect the link
+ */
+ bta_sys_start_timer(&p_scb->timer,
+ (UINT16)BTA_AV_API_CLOSE_EVT,
+ BTA_AV_CLOSE_REQ_TIME_VAL);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_av_connect_req
+**
+** Description Connect AVDTP connection.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_connect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ utl_freebuf((void **) &p_scb->p_disc_db);
+
+ if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR)
+ {
+ /* SNK initiated L2C connection while SRC was doing SDP. */
+ /* Wait until timeout to check if SNK starts signalling. */
+ APPL_TRACE_EVENT1("bta_av_connect_req: coll_mask = 0x%2X", p_scb->coll_mask);
+ return;
+ }
+
+ AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sdp_failed
+**
+** Description Service discovery failed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_sdp_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ if (!p_scb->open_status)
+ p_scb->open_status = BTA_AV_FAIL_SDP;
+
+ utl_freebuf((void **) &p_scb->p_disc_db);
+ bta_av_str_closed(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_disc_results
+**
+** Description Handle the AVDTP discover results. Search through the
+** results and find the first available stream, and get
+** its capabilities.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_disc_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ UINT8 num_snks = 0, i;
+
+ /* store number of stream endpoints returned */
+ p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
+
+ for (i = 0; i < p_scb->num_seps; i++)
+ {
+ /* steam not in use, is a sink, and is audio */
+ if ((p_scb->sep_info[i].in_use == FALSE) &&
+ (p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
+ (p_scb->sep_info[i].media_type == p_scb->media_type))
+ {
+ num_snks++;
+ }
+ }
+
+ p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, p_scb->peer_addr);
+ p_scb->num_disc_snks = num_snks;
+
+ /* if we got any */
+ if (p_scb->num_seps > 0)
+ {
+ /* initialize index into discovery results */
+ p_scb->sep_info_idx = 0;
+
+ /* get the capabilities of the first available stream */
+ bta_av_next_getcap(p_scb, p_data);
+ }
+ /* else we got discover response but with no streams; we're done */
+ else
+ {
+ bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_disc_res_as_acp
+**
+** Description Handle the AVDTP discover results. Search through the
+** results and find the first available stream, and get
+** its capabilities.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_disc_res_as_acp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ UINT8 num_snks = 0, i;
+
+ /* store number of stream endpoints returned */
+ p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
+
+
+
+ for (i = 0; i < p_scb->num_seps; i++)
+ {
+ /* steam is a sink, and is audio */
+ if ((p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
+ (p_scb->sep_info[i].media_type == p_scb->media_type))
+ {
+ p_scb->sep_info[i].in_use = FALSE;
+ num_snks++;
+ }
+ }
+
+ p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, p_scb->peer_addr);
+ p_scb->num_disc_snks = num_snks;
+
+ /* if we got any */
+ if (p_scb->num_seps > 0)
+ {
+ /* initialize index into discovery results */
+ p_scb->sep_info_idx = 0;
+
+ /* get the capabilities of the first available stream */
+ bta_av_next_getcap(p_scb, p_data);
+ }
+ /* else we got discover response but with no streams; we're done */
+ else
+ {
+ bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_save_caps
+**
+** Description report the SNK SEP capabilities to application
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_save_caps(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tAVDT_CFG cfg;
+ tAVDT_SEP_INFO *p_info = &p_scb->sep_info[p_scb->sep_info_idx];
+ UINT8 old_wait = p_scb->wait;
+ BOOLEAN getcap_done = FALSE;
+
+ APPL_TRACE_DEBUG3("bta_av_save_caps num_seps:%d sep_info_idx:%d wait:x%x",
+ p_scb->num_seps, p_scb->sep_info_idx, p_scb->wait);
+ memcpy(&cfg, p_scb->p_cap, sizeof(tAVDT_CFG));
+ /* let application know the capability of the SNK */
+ p_scb->p_cos->getcfg(p_scb->hndl, cfg.codec_info[BTA_AV_CODEC_TYPE_IDX],
+ cfg.codec_info, &p_scb->sep_info_idx, p_info->seid,
+ &cfg.num_protect, cfg.protect_info);
+
+ p_scb->sep_info_idx++;
+ if(p_scb->num_seps > p_scb->sep_info_idx)
+ {
+ /* Some devices have seps at the end of the discover list, which is not */
+ /* matching media type(video not audio). */
+ /* In this case, we are done with getcap without sending another */
+ /* request to AVDT. */
+ if (!bta_av_next_getcap(p_scb, p_data))
+ getcap_done = TRUE;
+ }
+ else
+ getcap_done = TRUE;
+
+ if (getcap_done)
+ {
+ /* we are done getting capabilities. restore the p_cb->sep_info_idx */
+ p_scb->sep_info_idx = 0;
+ p_scb->wait &= ~(BTA_AV_WAIT_ACP_CAPS_ON|BTA_AV_WAIT_ACP_CAPS_STARTED);
+ if (old_wait & BTA_AV_WAIT_ACP_CAPS_STARTED)
+ {
+ bta_av_start_ok (p_scb, NULL);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_set_use_rc
+**
+** Description set to use AVRC for this stream control block.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_set_use_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ p_scb->use_rc = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_cco_close
+**
+** Description call close call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_cco_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ UINT16 mtu;
+ mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
+
+ p_scb->p_cos->close(p_scb->hndl, p_scb->codec_type, mtu);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_open_failed
+**
+** Description Failed to open an AVDT stream
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ p_scb->open_status = BTA_AV_FAIL_STREAM;
+ bta_av_cco_close(p_scb, p_data);
+ AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_getcap_results
+**
+** Description Handle the AVDTP get capabilities results. Check the codec
+** type and see if it matches ours. If it does not, get the
+** capabilities of the next stream, if any.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tAVDT_CFG cfg;
+ UINT8 media_type;
+ tAVDT_SEP_INFO *p_info = &p_scb->sep_info[p_scb->sep_info_idx];
+
+ memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
+ cfg.num_codec = 1;
+ cfg.num_protect = p_scb->p_cap->num_protect;
+ memcpy(cfg.codec_info, p_scb->p_cap->codec_info, AVDT_CODEC_SIZE);
+ memcpy(cfg.protect_info, p_scb->p_cap->protect_info, AVDT_PROTECT_SIZE);
+ media_type = p_scb->p_cap->codec_info[BTA_AV_MEDIA_TYPE_IDX] >> 4;
+
+ APPL_TRACE_DEBUG1("num_codec %d", p_scb->p_cap->num_codec);
+ APPL_TRACE_DEBUG2("media type x%x, x%x", media_type, p_scb->media_type);
+#if AVDT_MULTIPLEXING == TRUE
+ APPL_TRACE_DEBUG2("mux x%x, x%x", cfg.mux_mask, p_scb->p_cap->mux_mask);
+#endif
+
+ /* if codec present and we get a codec configuration */
+ if ((p_scb->p_cap->num_codec != 0) &&
+ (media_type == p_scb->media_type) &&
+ (p_scb->p_cos->getcfg(p_scb->hndl, p_scb->p_cap->codec_info[BTA_AV_CODEC_TYPE_IDX],
+ cfg.codec_info, &p_scb->sep_info_idx, p_info->seid,
+ &cfg.num_protect, cfg.protect_info) == 0))
+ {
+#if AVDT_MULTIPLEXING == TRUE
+ cfg.mux_mask &= p_scb->p_cap->mux_mask;
+ APPL_TRACE_DEBUG1("mux_mask used x%x", cfg.mux_mask);
+#endif
+ /* save copy of codec type and configuration */
+ p_scb->codec_type = cfg.codec_info[BTA_AV_CODEC_TYPE_IDX];
+ memcpy(&p_scb->cfg, &cfg, sizeof(tAVDT_CFG));
+ bta_av_adjust_seps_idx(p_scb);
+ /* use only the services peer supports */
+ cfg.psc_mask &= p_scb->p_cap->psc_mask;
+ p_scb->cur_psc_mask = cfg.psc_mask;
+
+ /* open the stream */
+ AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
+ p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
+
+ if (!bta_av_is_rcfg_sst(p_scb))
+ {
+ /* free capabilities buffer */
+ utl_freebuf((void **) &p_scb->p_cap);
+ }
+ }
+ else
+ {
+ /* try the next stream, if any */
+ p_scb->sep_info_idx++;
+ bta_av_next_getcap(p_scb, p_data);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_av_setconfig_rej
+**
+** Description Send AVDTP set config reject.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_setconfig_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_REJECT reject;
+
+ APPL_TRACE_DEBUG0("bta_av_setconfig_rej");
+ AVDT_ConfigRsp(p_data->str_msg.handle, p_data->str_msg.msg.hdr.label, AVDT_ERR_BAD_STATE, 0);
+ bdcpy(reject.bd_addr, p_data->str_msg.bd_addr);
+ reject.hndl = p_scb->hndl;
+ (*bta_av_cb.p_cback)(BTA_AV_REJECT_EVT, (tBTA_AV *) &reject);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_discover_req
+**
+** Description Send an AVDTP discover request to the peer.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_discover_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ /* send avdtp discover request */
+
+ AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_conn_failed
+**
+** Description AVDTP connection failed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_conn_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ p_scb->open_status = BTA_AV_FAIL_STREAM;
+ bta_av_str_closed(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_do_start
+**
+** Description Start stream.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_do_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+ UINT8 cur_role;
+
+ APPL_TRACE_DEBUG3("bta_av_do_start sco_occupied:%d, role:x%x, started:%d", bta_av_cb.sco_occupied, p_scb->role, p_scb->started);
+ if (bta_av_cb.sco_occupied)
+ {
+ bta_av_start_failed(p_scb, p_data);
+ return;
+ }
+
+ /* disallow role switch during streaming, only if we are the master role
+ * i.e. allow role switch, if we are slave.
+ * It would not hurt us, if the peer device wants us to be master */
+ if ((BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
+ (cur_role == BTM_ROLE_MASTER) )
+ {
+ policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ }
+
+ bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+
+ if ((p_scb->started == FALSE) && ((p_scb->role & BTA_AV_ROLE_START_INT) == 0))
+ {
+ p_scb->role |= BTA_AV_ROLE_START_INT;
+ bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+
+ AVDT_StartReq(&p_scb->avdt_handle, 1);
+ }
+ else
+ {
+ bta_av_start_ok(p_scb, NULL);
+ }
+ APPL_TRACE_DEBUG2("started %d role:x%x", p_scb->started, p_scb->role);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_str_stopped
+**
+** Description Stream stopped.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_SUSPEND suspend_rsp;
+ UINT8 start = p_scb->started;
+ BOOLEAN sus_evt = TRUE;
+ BT_HDR *p_buf;
+ UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+
+ APPL_TRACE_ERROR2("bta_av_str_stopped:audio_open_cnt=%d, p_data %x",
+ bta_av_cb.audio_open_cnt, p_data);
+
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
+ policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+
+ if(p_scb->co_started)
+ {
+ bta_av_stream_chg(p_scb, FALSE);
+ p_scb->co_started = FALSE;
+
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->codec_type);
+ L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
+ }
+
+ /* if q_info.a2d is not empty, drop it now */
+ if(BTA_AV_CHNL_AUDIO == p_scb->chnl)
+ {
+ while((p_buf = (BT_HDR*)GKI_dequeue (&p_scb->q_info.a2d)) != NULL)
+ GKI_freebuf(p_buf);
+
+ /* drop the audio buffers queued in L2CAP */
+ if(p_data && p_data->api_stop.flush)
+ L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+ }
+
+ suspend_rsp.chnl = p_scb->chnl;
+ suspend_rsp.hndl = p_scb->hndl;
+
+ if (p_data && p_data->api_stop.suspend)
+ {
+ APPL_TRACE_DEBUG2("suspending: %d, sup:%d", start, p_scb->suspend_sup);
+ if ((start) && (p_scb->suspend_sup))
+ {
+ sus_evt = FALSE;
+ p_scb->l2c_bufs = 0;
+ AVDT_SuspendReq(&p_scb->avdt_handle, 1);
+ }
+
+ if(sus_evt)
+ {
+ suspend_rsp.status = BTA_AV_SUCCESS;
+ suspend_rsp.initiator = TRUE;
+ (*bta_av_cb.p_cback)(BTA_AV_SUSPEND_EVT, (tBTA_AV *) &suspend_rsp);
+ }
+ }
+ else
+ {
+ suspend_rsp.status = BTA_AV_SUCCESS;
+ suspend_rsp.initiator = TRUE;
+ APPL_TRACE_EVENT1("bta_av_str_stopped status %d", suspend_rsp.status);
+
+ (*bta_av_cb.p_cback)(BTA_AV_STOP_EVT, (tBTA_AV *) &suspend_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_reconfig
+**
+** Description process the reconfigure request.
+** save the parameter in control block and
+** suspend, reconfigure or close the stream
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_reconfig (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tAVDT_CFG *p_cfg;
+ tBTA_AV_API_STOP stop;
+ tBTA_AV_RECONFIG evt;
+ tBTA_AV_API_RCFG *p_rcfg = &p_data->api_reconfig;
+
+ APPL_TRACE_DEBUG4("bta_av_reconfig r:%d, s:%d idx: %d (o:%d)",
+ p_scb->recfg_sup, p_scb->suspend_sup,
+ p_scb->rcfg_idx, p_scb->sep_info_idx);
+
+ p_scb->num_recfg = 0;
+ /* store the new configuration in control block */
+ if (p_scb->p_cap == NULL)
+ {
+ p_scb->p_cap = (tAVDT_CFG *) GKI_getbuf(sizeof(tAVDT_CFG));
+ }
+ if((p_cfg = p_scb->p_cap) == NULL)
+ {
+ /* report failure */
+ evt.status = BTA_AV_FAIL_RESOURCES;
+ evt.chnl = p_scb->chnl;
+ evt.hndl = p_scb->hndl;
+ (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+
+ /* this event is not possible in this state.
+ * use it to bring the SSM back to open state */
+ bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_OK_EVT, NULL);
+ return;
+ }
+
+ /*if(bta_av_cb.features & BTA_AV_FEAT_RCCT)*/
+ bta_sys_stop_timer(&p_scb->timer);
+
+ memcpy(p_cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
+ p_cfg->num_protect = p_rcfg->num_protect;
+ memcpy(p_cfg->codec_info, p_rcfg->codec_info, AVDT_CODEC_SIZE);
+ memcpy(p_cfg->protect_info, p_rcfg->p_protect_info, p_rcfg->num_protect);
+ p_scb->rcfg_idx = p_rcfg->sep_info_idx;
+ p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
+
+ /* if the requested index differs from the current one, we can only close/open */
+ if ((p_scb->rcfg_idx == p_scb->sep_info_idx) &&
+ (p_rcfg->suspend)&& (p_scb->recfg_sup) && (p_scb->suspend_sup))
+ {
+ if(p_scb->started)
+ {
+ stop.flush = FALSE;
+ stop.suspend = TRUE;
+ bta_av_str_stopped(p_scb, (tBTA_AV_DATA *)&stop);
+ }
+ else
+ {
+ APPL_TRACE_DEBUG0("Reconfig");
+ AVDT_ReconfigReq(p_scb->avdt_handle, p_scb->p_cap);
+ p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
+ }
+ }
+ else
+ {
+ /* close the stream */
+ APPL_TRACE_DEBUG1("close/open num_protect: %d", p_cfg->num_protect);
+ if(p_scb->started)
+ bta_av_str_stopped(p_scb, NULL);
+ p_scb->started = FALSE;
+
+ /* drop the buffers queued in L2CAP */
+ L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+
+ AVDT_CloseReq(p_scb->avdt_handle);
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_data_path
+**
+** Description Handle stream data path.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_data_path (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ BT_HDR *p_buf;
+ UINT32 data_len;
+ UINT32 timestamp;
+ BOOLEAN new_buf = FALSE;
+ UINT8 m_pt = 0x60 | p_scb->codec_type;
+
+ if (!p_scb->cong)
+ {
+ /*
+ APPL_TRACE_ERROR1("q: %d", p_scb->l2c_bufs);
+ */
+ //Always get the current number of bufs que'd up
+ p_scb->l2c_bufs = (UINT8)L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_GET);
+
+ p_buf = (BT_HDR *)GKI_dequeue (&p_scb->q_info.a2d);
+ if(p_buf)
+ {
+ /* use q_info.a2d data, read the timestamp */
+ timestamp = *(UINT32 *)(p_buf + 1);
+ }
+ else
+ {
+ new_buf = TRUE;
+ /* q_info.a2d empty, call co_data, dup data to other channels */
+ p_buf = (BT_HDR *)p_scb->p_cos->data(p_scb->codec_type, &data_len,
+ ×tamp);
+
+ if (p_buf)
+ {
+ /* use the offset area for the time stamp */
+ *(UINT32 *)(p_buf + 1) = timestamp;
+
+ /* dup the data to other channels */
+ bta_av_dup_audio_buf(p_scb, p_buf);
+ }
+ }
+
+ if(p_buf)
+ {
+ if(p_scb->l2c_bufs < (BTA_AV_QUEUE_DATA_CHK_NUM))
+ {
+ /* there's a buffer, just queue it to L2CAP */
+ /* There's no need to increment it here, it is always read from L2CAP see above */
+ /* p_scb->l2c_bufs++; */
+ /*
+ APPL_TRACE_ERROR1("qw: %d", p_scb->l2c_bufs);
+ */
+ AVDT_WriteReq(p_scb->avdt_handle, p_buf, timestamp, m_pt);
+ p_scb->cong = TRUE;
+ }
+ else
+ {
+ /* there's a buffer, but L2CAP does not seem to be moving data */
+ if(new_buf)
+ {
+ /* just got this buffer from co_data,
+ * put it in queue */
+ GKI_enqueue(&p_scb->q_info.a2d, p_buf);
+ }
+ else
+ {
+ /* just dequeue it from the q_info.a2d */
+ if(p_scb->q_info.a2d.count < 3)
+ {
+ /* put it back to the queue */
+ GKI_enqueue_head (&p_scb->q_info.a2d, p_buf);
+ }
+ else
+ {
+ /* too many buffers in q_info.a2d, drop it. */
+ bta_av_co_audio_drop(p_scb->hndl);
+ GKI_freebuf(p_buf);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_start_ok
+**
+** Description Stream started.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_START start;
+ tBTA_AV_API_STOP stop;
+ BOOLEAN initiator = FALSE;
+ BOOLEAN suspend = FALSE;
+ UINT16 flush_to;
+ UINT8 new_role = p_scb->role;
+ BT_HDR hdr;
+
+ APPL_TRACE_DEBUG2("bta_av_start_ok wait:x%x, role:x%x", p_scb->wait, p_scb->role);
+
+ p_scb->started = TRUE;
+ if (p_scb->sco_suspend)
+ {
+ p_scb->sco_suspend = FALSE;
+ }
+
+ if (new_role & BTA_AV_ROLE_START_INT)
+ initiator = TRUE;
+
+ if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_FAILED)
+ {
+ /* role switch has failed */
+ p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_FAILED;
+ p_data = (tBTA_AV_DATA *)&hdr;
+ hdr.offset = BTA_AV_RS_FAIL;
+ }
+ APPL_TRACE_DEBUG1("wait:x%x", p_scb->wait);
+
+ if (p_data && (p_data->hdr.offset != BTA_AV_RS_NONE))
+ {
+ p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+ if (p_data->hdr.offset == BTA_AV_RS_FAIL)
+ {
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ start.chnl = p_scb->chnl;
+ start.status = BTA_AV_FAIL_ROLE;
+ start.hndl = p_scb->hndl;
+ start.initiator = initiator;
+ (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+ return;
+ }
+ }
+
+ if (!bta_av_link_role_ok(p_scb, A2D_SET_ONE_BIT))
+ p_scb->q_tag = BTA_AV_Q_TAG_START;
+ else
+ {
+ /* The wait flag may be set here while we are already master on the link */
+ /* this could happen if a role switch complete event occurred during reconfig */
+ /* if we are now master on the link, there is no need to wait for the role switch, */
+ /* complete anymore so we can clear the wait for role switch flag */
+ p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+ }
+
+ if (p_scb->wait & (BTA_AV_WAIT_ROLE_SW_RES_OPEN|BTA_AV_WAIT_ROLE_SW_RES_START))
+ {
+ p_scb->wait |= BTA_AV_WAIT_ROLE_SW_STARTED;
+ p_scb->q_tag = BTA_AV_Q_TAG_START;
+ }
+
+ if (p_scb->wait & BTA_AV_WAIT_ACP_CAPS_ON)
+ {
+ p_scb->wait |= BTA_AV_WAIT_ACP_CAPS_STARTED;
+ }
+
+ if (p_scb->wait)
+ {
+ APPL_TRACE_DEBUG2("wait:x%x q_tag:%d- not started", p_scb->wait, p_scb->q_tag);
+ return;
+ }
+
+ /* tell role manager to check M/S role */
+ bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+
+ bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+
+ if(p_scb->media_type == AVDT_MEDIA_AUDIO)
+ {
+ /* in normal logic, conns should be bta_av_cb.audio_count - 1,
+ * However, bta_av_stream_chg is not called to increase bta_av_cb.audio_count yet.
+ * If the code were to be re-arranged for some reasons, this number may need to be changed
+ */
+ p_scb->co_started = bta_av_cb.audio_open_cnt;
+ flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1];
+ }
+ else
+ {
+ flush_to = p_bta_av_cfg->video_flush_to;
+ }
+ L2CA_SetFlushTimeout(p_scb->peer_addr, flush_to );
+
+ /* clear the congestion flag */
+ p_scb->cong = FALSE;
+
+ if (new_role & BTA_AV_ROLE_START_INT)
+ {
+ new_role &= ~BTA_AV_ROLE_START_INT;
+ }
+ else if ((new_role & BTA_AV_ROLE_AD_ACP) && (new_role & BTA_AV_ROLE_SUSPEND_OPT))
+ {
+ suspend = TRUE;
+ }
+
+ if (!suspend)
+ {
+ p_scb->q_tag = BTA_AV_Q_TAG_STREAM;
+ bta_av_stream_chg(p_scb, TRUE);
+ }
+
+ {
+ p_scb->role = new_role;
+ p_scb->role &= ~BTA_AV_ROLE_AD_ACP;
+ p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT;
+
+ p_scb->p_cos->start(p_scb->hndl, p_scb->codec_type);
+ p_scb->co_started = TRUE;
+
+ APPL_TRACE_DEBUG3("bta_av_start_ok suspending: %d, role:x%x, init %d",
+ suspend, p_scb->role, initiator);
+
+ start.suspending = suspend;
+ start.initiator = initiator;
+ start.chnl = p_scb->chnl;
+ start.status = BTA_AV_SUCCESS;
+ start.hndl = p_scb->hndl;
+ (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+
+ if(suspend)
+ {
+ p_scb->role |= BTA_AV_ROLE_SUSPEND;
+ p_scb->cong = TRUE; /* do not allow the media data to go through */
+ /* do not duplicate the media packets to this channel */
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->codec_type);
+ p_scb->co_started = FALSE;
+ stop.flush = FALSE;
+ stop.suspend = TRUE;
+ bta_av_ssm_execute(p_scb, BTA_AV_AP_STOP_EVT, (tBTA_AV_DATA *)&stop);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_start_failed
+**
+** Description Stream start failed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_start_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_START start;
+
+ if(p_scb->started == FALSE && p_scb->co_started == FALSE)
+ {
+ /* if start failed, clear role */
+ p_scb->role &= ~BTA_AV_ROLE_START_INT;
+
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ start.chnl = p_scb->chnl;
+ start.status = BTA_AV_FAIL;
+ start.initiator = TRUE;
+ start.hndl = p_scb->hndl;
+ (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+ }
+
+ bta_sys_set_policy(BTA_ID_AV, (HCI_ENABLE_SNIFF_MODE|HCI_ENABLE_MASTER_SLAVE_SWITCH), p_scb->peer_addr);
+ p_scb->sco_suspend = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_str_closed
+**
+** Description Stream closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV data;
+ tBTA_AV_EVT event;
+ UINT16 mtu;
+ UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+
+ if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
+ policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+ if (bta_av_cb.audio_open_cnt <= 1)
+ {
+ /* last connection - restore the allow switch flag */
+ L2CA_SetDesireRole(L2CAP_ROLE_ALLOW_SWITCH);
+ }
+
+ if (p_scb->open_status)
+ {
+ /* must be failure when opening the stream */
+ bdcpy(data.open.bd_addr, p_scb->peer_addr);
+ data.open.status = p_scb->open_status;
+ data.open.chnl = p_scb->chnl;
+ data.open.hndl = p_scb->hndl;
+ event = BTA_AV_OPEN_EVT;
+ p_scb->open_status = BTA_AV_SUCCESS;
+
+ bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+ bta_av_cleanup(p_scb, p_data);
+ (*bta_av_cb.p_cback)(event, &data);
+ }
+ else
+ {
+ /* do stop if we were started */
+ if (p_scb->co_started)
+ {
+ bta_av_str_stopped(p_scb, NULL);
+ }
+
+ /* Update common mtu shared by remaining connectons */
+ mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
+
+ {
+ p_scb->p_cos->close(p_scb->hndl, p_scb->codec_type, mtu);
+ data.close.chnl = p_scb->chnl;
+ data.close.hndl = p_scb->hndl;
+ event = BTA_AV_CLOSE_EVT;
+
+ bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+ bta_av_cleanup(p_scb, p_data);
+ (*bta_av_cb.p_cback)(event, &data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_clr_cong
+**
+** Description Clear stream congestion flag.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_clr_cong (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ if(p_scb->co_started)
+ p_scb->cong = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_suspend_cfm
+**
+** Description process the suspend response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_SUSPEND suspend_rsp;
+ UINT8 err_code = p_data->str_msg.msg.hdr.err_code;
+ UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+
+ APPL_TRACE_DEBUG2 ("bta_av_suspend_cfm:audio_open_cnt = %d, err_code = %d",
+ bta_av_cb.audio_open_cnt, err_code);
+
+ suspend_rsp.status = BTA_AV_SUCCESS;
+ if(err_code)
+ {
+ p_scb->suspend_sup = FALSE;
+ suspend_rsp.status = BTA_AV_FAIL;
+
+ APPL_TRACE_ERROR0 ("bta_av_suspend_cfm: suspend failed, closing connection");
+
+ /* SUSPEND failed. Close connection. */
+ bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, NULL);
+ }
+ else
+ {
+ /* only set started to FALSE when suspend is successful */
+ p_scb->started = FALSE;
+ }
+
+ if(p_scb->role & BTA_AV_ROLE_SUSPEND)
+ {
+ p_scb->role &= ~BTA_AV_ROLE_SUSPEND;
+ p_scb->cong = FALSE;
+ }
+
+ bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+ if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
+ policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+
+ /* in case that we received suspend_ind, we may need to call co_stop here */
+ if(p_scb->co_started)
+ {
+ bta_av_stream_chg(p_scb, FALSE);
+
+ {
+ p_scb->co_started = FALSE;
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->codec_type);
+ }
+ L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
+ }
+
+ {
+ suspend_rsp.chnl = p_scb->chnl;
+ suspend_rsp.hndl = p_scb->hndl;
+ suspend_rsp.initiator = p_data->str_msg.initiator;
+ (*bta_av_cb.p_cback)(BTA_AV_SUSPEND_EVT, (tBTA_AV *) &suspend_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rcfg_str_ok
+**
+** Description report reconfigure successful
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rcfg_str_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RECONFIG evt;
+
+ p_scb->l2c_cid = AVDT_GetL2CapChannel(p_scb->avdt_handle);
+ APPL_TRACE_DEBUG1("bta_av_rcfg_str_ok: l2c_cid: %d", p_scb->l2c_cid);
+
+ /* rc listen */
+ bta_av_st_rc_timer(p_scb, NULL);
+ utl_freebuf((void **)&p_scb->p_cap);
+
+ /* No need to keep the role bits once reconfig is done. */
+ p_scb->role &= ~BTA_AV_ROLE_AD_ACP;
+ p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT;
+ p_scb->role &= ~BTA_AV_ROLE_START_INT;
+
+ {
+ /* reconfigure success */
+ evt.status = BTA_AV_SUCCESS;
+ evt.chnl = p_scb->chnl;
+ evt.hndl = p_scb->hndl;
+ (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rcfg_failed
+**
+** Description process reconfigure failed
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rcfg_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RECONFIG evt;
+
+ APPL_TRACE_DEBUG2("bta_av_rcfg_failed num_recfg: %d, conn_lcb:0x%x",
+ p_scb->num_recfg, bta_av_cb.conn_lcb);
+ if(p_scb->num_recfg > BTA_AV_RECONFIG_RETRY)
+ {
+ bta_av_cco_close(p_scb, p_data);
+ /* report failure */
+ evt.status = BTA_AV_FAIL_STREAM;
+ evt.chnl = p_scb->chnl;
+ evt.hndl = p_scb->hndl;
+ (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+ /* go to closing state */
+ bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, NULL);
+ }
+ else
+ {
+ /* open failed. try again */
+ p_scb->num_recfg++;
+ if(bta_av_cb.conn_lcb)
+ {
+ AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+ }
+ else
+ {
+ bta_av_connect_req(p_scb, NULL);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rcfg_connect
+**
+** Description stream closed. reconnect the stream
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rcfg_connect (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ p_scb->cong = FALSE;
+ p_scb->num_recfg++;
+ APPL_TRACE_DEBUG1("bta_av_rcfg_connect num_recfg: %d", p_scb->num_recfg);
+ if(p_scb->num_recfg > BTA_AV_RECONFIG_RETRY)
+ {
+ /* let bta_av_rcfg_failed report fail */
+ bta_av_rcfg_failed(p_scb, NULL);
+ }
+ else
+ AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rcfg_discntd
+**
+** Description AVDT disconnected. reconnect the stream
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rcfg_discntd (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RECONFIG evt;
+
+ APPL_TRACE_DEBUG1("bta_av_rcfg_discntd num_recfg: %d", p_scb->num_recfg);
+ p_scb->num_recfg++;
+ if(p_scb->num_recfg > BTA_AV_RECONFIG_RETRY)
+ {
+ /* report failure */
+ evt.status = BTA_AV_FAIL_STREAM;
+ evt.chnl = p_scb->chnl;
+ evt.hndl = p_scb->hndl;
+ (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+ /* report close event & go to init state */
+ bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
+ }
+ else
+ AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_suspend_cont
+**
+** Description received the suspend response.
+** continue to reconfigure the stream
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ UINT8 err_code = p_data->str_msg.msg.hdr.err_code;
+ tBTA_AV_RECONFIG evt;
+
+ p_scb->started = FALSE;
+ p_scb->cong = FALSE;
+ if(err_code)
+ {
+ if(AVDT_ERR_CONNECT == err_code)
+ {
+ /* report failure */
+ evt.status = BTA_AV_FAIL;
+ (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+ bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("suspend rejected, try close");
+ p_scb->suspend_sup = FALSE;
+
+ /* drop the buffers queued in L2CAP */
+ L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+
+ AVDT_CloseReq(p_scb->avdt_handle);
+ }
+ }
+ else
+ {
+ APPL_TRACE_DEBUG0("bta_av_suspend_cont calling AVDT_ReconfigReq");
+ /* reconfig the stream */
+
+ AVDT_ReconfigReq(p_scb->avdt_handle, p_scb->p_cap);
+ p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rcfg_cfm
+**
+** Description if reconfigure is successful, report the event
+** otherwise, close the stream.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rcfg_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ UINT8 err_code = p_data->str_msg.msg.hdr.err_code;
+
+ /*
+ APPL_TRACE_DEBUG0("bta_av_rcfg_cfm");
+ */
+ if(err_code)
+ {
+ APPL_TRACE_ERROR0("reconfig rejected, try close");
+ p_scb->recfg_sup = FALSE;
+ /* started flag is FALSE when reconfigure command is sent */
+ /* drop the buffers queued in L2CAP */
+ L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+ AVDT_CloseReq(p_scb->avdt_handle);
+ }
+ else
+ {
+ /* take the SSM back to OPEN state */
+ bta_av_ssm_execute(p_scb, BTA_AV_STR_OPEN_OK_EVT, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rcfg_open
+**
+** Description AVDT is connected. open the stream with the new configuration
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rcfg_open (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1("bta_av_rcfg_open, num_disc_snks = %d", p_scb->num_disc_snks);
+
+ if (p_scb->num_disc_snks == 0)
+ {
+ /* Need to update call-out module so that it will be ready for discover */
+ p_scb->p_cos->stop(p_scb->hndl, p_scb->codec_type);
+
+ /* send avdtp discover request */
+ AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS, bta_av_dt_cback[p_scb->hdi]);
+ }
+ else
+ {
+ p_scb->codec_type = p_scb->p_cap->codec_info[BTA_AV_CODEC_TYPE_IDX];
+ memcpy(p_scb->cfg.codec_info, p_scb->p_cap->codec_info, AVDT_CODEC_SIZE);
+ /* we may choose to use a different SEP at reconfig.
+ * adjust the sep_idx now */
+ bta_av_adjust_seps_idx(p_scb);
+
+ /* open the stream with the new config */
+ p_scb->sep_info_idx = p_scb->rcfg_idx;
+ AVDT_OpenReq(p_scb->avdt_handle, p_scb->peer_addr,
+ p_scb->sep_info[p_scb->sep_info_idx].seid, p_scb->p_cap);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_av_security_rej
+**
+** Description Send an AVDTP security reject.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_security_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ AVDT_SecurityRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_BAD_STATE,
+ NULL, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_chk_2nd_start
+**
+** Description check if this is 2nd stream and if it needs to be started.
+** This function needs to be kept very similar to bta_av_chk_start
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_chk_2nd_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_SCB *p_scbi;
+ int i;
+ BOOLEAN new_started = FALSE;
+
+
+ if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2))
+ {
+ /* more than one audio channel is connected */
+ if (!(p_scb->role & BTA_AV_ROLE_SUSPEND_OPT))
+ {
+ /* this channel does not need to be reconfigured.
+ * if there is other channel streaming, start the stream now */
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scbi = bta_av_cb.p_scb[i];
+ if(p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started)
+ {
+ if (!new_started)
+ {
+ /* start the new stream */
+ new_started = TRUE;
+ bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
+ }
+ /* may need to update the flush timeout of this already started stream */
+ if (p_scbi->co_started != bta_av_cb.audio_open_cnt)
+ {
+ p_scbi->co_started = bta_av_cb.audio_open_cnt;
+ L2CA_SetFlushTimeout(p_scbi->peer_addr, p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1] );
+ }
+ }
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_open_rc
+**
+** Description Send a message to main SM to open RC channel.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_open_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_START start;
+
+ APPL_TRACE_DEBUG3("bta_av_open_rc use_rc: %d, wait: x%x role:x%x", p_scb->use_rc, p_scb->wait, p_scb->role);
+ if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) && (p_scb->q_tag == BTA_AV_Q_TAG_START))
+ {
+ /* waiting for role switch for some reason & the timer expires */
+ if (!bta_av_link_role_ok(p_scb, A2D_SET_ONE_BIT))
+ {
+ APPL_TRACE_ERROR0 ("failed to start streaming for role management reasons!!");
+ bta_sys_stop_timer(&p_scb->timer);
+ start.chnl = p_scb->chnl;
+ start.status = BTA_AV_FAIL_ROLE;
+ start.initiator = TRUE;
+ start.hndl = p_scb->hndl;
+ p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+ bta_av_cb.rs_idx = 0;
+ (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+ }
+ else
+ {
+ /* role switch is done. continue to start streaming */
+ bta_av_cb.rs_idx = 0;
+ p_data->hdr.offset = BTA_AV_RS_OK;
+ bta_av_start_ok (p_scb, p_data);
+ }
+ return;
+ }
+
+ if(p_scb->use_rc == TRUE || (p_scb->role & BTA_AV_ROLE_AD_ACP) )
+ {
+ if(bta_av_cb.disc)
+ {
+ /* AVRC discover db is in use */
+ if(p_scb->rc_handle == BTA_AV_RC_HANDLE_NONE)
+ {
+ /* AVRC channel is not connected. delay a little bit */
+ if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) == 0)
+ bta_sys_start_timer(&p_scb->timer, BTA_AV_AVRC_TIMER_EVT, BTA_AV_RC_DISC_TIME_VAL);
+ else
+ p_scb->wait |= BTA_AV_WAIT_CHECK_RC;
+ }
+ }
+ else
+ {
+ /* use main SM for AVRC SDP activities */
+ bta_av_rc_disc((UINT8)(p_scb->hdi + 1));
+ }
+ }
+ else
+ {
+ if(BTA_AV_RC_HANDLE_NONE != p_scb->rc_handle)
+ {
+ /* the open API said that this handle does not want a RC connection.
+ * disconnect it now */
+ AVRC_Close(p_scb->rc_handle);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_open_at_inc
+**
+** Description This function is called if API open is called by application
+** while state-machine is at incoming state.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_API_OPEN *p_buf;
+
+ memcpy (&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
+
+ if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR)
+ {
+ p_scb->coll_mask |= BTA_AV_COLL_API_CALLED;
+
+ /* API open will be handled at timeout if SNK did not start signalling. */
+ /* API open will be ignored if SNK starts signalling. */
+ }
+ else
+ {
+ /* SNK did not start signalling, API was called N seconds timeout. */
+ /* We need to switch to INIT state and start opening connection. */
+ p_scb->coll_mask = 0;
+ bta_av_set_scb_sst_init (p_scb);
+
+ if ((p_buf = (tBTA_AV_API_OPEN *) GKI_getbuf(sizeof(tBTA_AV_API_OPEN))) != NULL)
+ {
+ memcpy(p_buf, &(p_scb->open_api), sizeof(tBTA_AV_API_OPEN));
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+}
+
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
new file mode 100644
index 0000000..a47921a
--- /dev/null
+++ b/bta/av/bta_av_act.c
@@ -0,0 +1,1941 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains action functions for advanced audio/video main state
+ * machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_av_api.h"
+#include "bta_av_int.h"
+#include "avdt_api.h"
+#include "bd.h"
+#include "utl.h"
+#include "l2c_api.h"
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+/* the timer in milliseconds to wait for open req after setconfig for incoming connections */
+#ifndef BTA_AV_SIG_TIME_VAL
+#define BTA_AV_SIG_TIME_VAL 8000
+#endif
+
+/* In millisec to wait for signalling from SNK when it is initiated from SNK. */
+/* If not, we will start signalling from SRC. */
+#ifndef BTA_AV_ACP_SIG_TIME_VAL
+#define BTA_AV_ACP_SIG_TIME_VAL 2000
+#endif
+
+static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle);
+
+/*******************************************************************************
+**
+** Function bta_av_get_rcb_by_shdl
+**
+** Description find the RCB associated with the given SCB handle.
+**
+** Returns tBTA_AV_RCB
+**
+*******************************************************************************/
+tBTA_AV_RCB * bta_av_get_rcb_by_shdl(UINT8 shdl)
+{
+ tBTA_AV_RCB *p_rcb = NULL;
+ int i;
+
+ for (i=0; i<BTA_AV_NUM_RCB; i++)
+ {
+ if (bta_av_cb.rcb[i].shdl == shdl && bta_av_cb.rcb[i].handle != BTA_AV_RC_HANDLE_NONE)
+ {
+ p_rcb = &bta_av_cb.rcb[i];
+ break;
+ }
+ }
+ return p_rcb;
+}
+#define BTA_AV_STS_NO_RSP 0xFF /* a number not used by tAVRC_STS */
+
+/*******************************************************************************
+**
+** Function bta_av_del_rc
+**
+** Description delete the given AVRC handle.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_del_rc(tBTA_AV_RCB *p_rcb)
+{
+ tBTA_AV_SCB *p_scb;
+ UINT8 rc_handle; /* connected AVRCP handle */
+
+ if(p_rcb->handle != BTA_AV_RC_HANDLE_NONE)
+ {
+ if(p_rcb->shdl)
+ {
+ p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
+ if(p_scb)
+ {
+ APPL_TRACE_DEBUG3("bta_av_del_rc shdl:%d, srch:%d rc_handle:%d", p_rcb->shdl,
+ p_scb->rc_handle, p_rcb->handle);
+ if(p_scb->rc_handle == p_rcb->handle)
+ p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
+ /* just in case the RC timer is active
+ if(bta_av_cb.features & BTA_AV_FEAT_RCCT && p_scb->chnl == BTA_AV_CHNL_AUDIO) */
+ bta_sys_stop_timer(&p_scb->timer);
+ }
+ }
+
+ APPL_TRACE_EVENT4("bta_av_del_rc handle: %d status=0x%x, rc_acp_handle:%d, idx:%d",
+ p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle, bta_av_cb.rc_acp_idx);
+ rc_handle = p_rcb->handle;
+ if(!(p_rcb->status & BTA_AV_RC_CONN_MASK) ||
+ ((p_rcb->status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT) )
+ {
+ p_rcb->status = 0;
+ p_rcb->handle = BTA_AV_RC_HANDLE_NONE;
+ p_rcb->shdl = 0;
+ p_rcb->lidx = 0;
+ }
+ /* else ACP && connected. do not clear the handle yet */
+ AVRC_Close(rc_handle);
+ if (rc_handle == bta_av_cb.rc_acp_handle)
+ bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE;
+ APPL_TRACE_EVENT4("end del_rc handle: %d status=0x%x, rc_acp_handle:%d, lidx:%d",
+ p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle, p_rcb->lidx);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_av_close_all_rc
+**
+** Description close the all AVRC handle.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_close_all_rc(tBTA_AV_CB *p_cb)
+{
+ int i;
+
+ for(i=0; i<BTA_AV_NUM_RCB; i++)
+ {
+ if ((p_cb->disabling == TRUE) || (bta_av_cb.rcb[i].shdl != 0))
+ bta_av_del_rc(&bta_av_cb.rcb[i]);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_del_sdp_rec
+**
+** Description delete the given SDP record handle.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_del_sdp_rec(UINT32 *p_sdp_handle)
+{
+ if(*p_sdp_handle != 0)
+ {
+ SDP_DeleteRecord(*p_sdp_handle);
+ *p_sdp_handle = 0;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_avrc_sdp_cback
+**
+** Description AVRCP service discovery callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_avrc_sdp_cback(UINT16 status)
+{
+ BT_HDR *p_msg;
+
+ if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = BTA_AV_SDP_AVRC_DISC_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_ctrl_cback
+**
+** Description AVRCP control callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_rc_ctrl_cback(UINT8 handle, UINT8 event, UINT16 result, BD_ADDR peer_addr)
+{
+ tBTA_AV_RC_CONN_CHG *p_msg;
+ UINT16 msg_event = 0;
+
+#if (defined(BTA_AV_MIN_DEBUG_TRACES) && BTA_AV_MIN_DEBUG_TRACES == TRUE)
+ APPL_TRACE_EVENT2("rc_ctrl handle: %d event=0x%x", handle, event);
+#else
+ APPL_TRACE_EVENT2("bta_av_rc_ctrl_cback handle: %d event=0x%x", handle, event);
+#endif
+ if (event == AVRC_OPEN_IND_EVT)
+ {
+ /* save handle of opened connection
+ bta_av_cb.rc_handle = handle;*/
+
+ msg_event = BTA_AV_AVRC_OPEN_EVT;
+ }
+ else if (event == AVRC_CLOSE_IND_EVT)
+ {
+ msg_event = BTA_AV_AVRC_CLOSE_EVT;
+ }
+
+ if (msg_event)
+ {
+ if ((p_msg = (tBTA_AV_RC_CONN_CHG *) GKI_getbuf(sizeof(tBTA_AV_RC_CONN_CHG))) != NULL)
+ {
+ p_msg->hdr.event = msg_event;
+ p_msg->handle = handle;
+ if(peer_addr)
+ bdcpy(p_msg->peer_addr, peer_addr);
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_msg_cback
+**
+** Description AVRCP message callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_rc_msg_cback(UINT8 handle, UINT8 label, UINT8 opcode, tAVRC_MSG *p_msg)
+{
+ tBTA_AV_RC_MSG *p_buf;
+ UINT8 *p_data = NULL;
+ UINT8 **p_p_data = NULL;
+ UINT16 data_len = 0;
+
+#if (defined(BTA_AV_MIN_DEBUG_TRACES) && BTA_AV_MIN_DEBUG_TRACES == TRUE)
+ APPL_TRACE_ERROR2("rc_msg handle: %d opcode=0x%x", handle, opcode);
+#else
+ APPL_TRACE_EVENT2("bta_av_rc_msg_cback handle: %d opcode=0x%x", handle, opcode);
+#endif
+ /* determine size of buffer we need */
+ if (opcode == AVRC_OP_VENDOR && p_msg->vendor.p_vendor_data != NULL)
+ {
+ p_data = p_msg->vendor.p_vendor_data;
+ p_p_data = &p_msg->vendor.p_vendor_data;
+ data_len = (UINT16) p_msg->vendor.vendor_len;
+ }
+ else if (opcode == AVRC_OP_PASS_THRU && p_msg->pass.p_pass_data != NULL)
+ {
+ p_data = p_msg->pass.p_pass_data;
+ p_p_data = &p_msg->pass.p_pass_data;
+ data_len = (UINT16) p_msg->pass.pass_len;
+ }
+
+ if ((p_buf = (tBTA_AV_RC_MSG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_RC_MSG) + data_len))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_AVRC_MSG_EVT;
+ p_buf->handle = handle;
+ p_buf->label = label;
+ p_buf->opcode = opcode;
+ memcpy(&p_buf->msg, p_msg, sizeof(tAVRC_MSG));
+ if (p_data != NULL)
+ {
+ memcpy((UINT8 *)(p_buf + 1), p_data, data_len);
+ *p_p_data = (UINT8 *)(p_buf + 1);
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_create
+**
+** Description alloc RCB and call AVRC_Open
+**
+** Returns the created rc handle
+**
+*******************************************************************************/
+UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx)
+{
+ tAVRC_CONN_CB ccb;
+ BD_ADDR_PTR bda = (BD_ADDR_PTR)bd_addr_any;
+ UINT8 status = BTA_AV_RC_ROLE_ACP;
+ tBTA_AV_SCB *p_scb = p_cb->p_scb[shdl - 1];
+ int i;
+ UINT8 rc_handle;
+ tBTA_AV_RCB *p_rcb;
+
+ if(role == AVCT_INT)
+ {
+ bda = p_scb->peer_addr;
+ status = BTA_AV_RC_ROLE_INT;
+ }
+ else
+ {
+ if ((p_rcb = bta_av_get_rcb_by_shdl(shdl)) != NULL )
+ {
+ APPL_TRACE_ERROR1("bta_av_rc_create ACP handle exist for shdl:%d", shdl);
+ return p_rcb->handle;
+ }
+ }
+
+ ccb.p_ctrl_cback = bta_av_rc_ctrl_cback;
+ ccb.p_msg_cback = bta_av_rc_msg_cback;
+ ccb.company_id = p_bta_av_cfg->company_id;
+ ccb.conn = role;
+ /* note: BTA_AV_FEAT_RCTG = AVRC_CT_TARGET, BTA_AV_FEAT_RCCT = AVRC_CT_CONTROL */
+ ccb.control = p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | AVRC_CT_PASSIVE);
+
+
+ if (AVRC_Open(&rc_handle, &ccb, bda) != AVRC_SUCCESS)
+ return BTA_AV_RC_HANDLE_NONE;
+
+ i = rc_handle;
+ p_rcb = &p_cb->rcb[i];
+
+ if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE)
+ {
+ APPL_TRACE_ERROR1("bta_av_rc_create found duplicated handle:%d", rc_handle);
+ }
+
+ p_rcb->handle = rc_handle;
+ p_rcb->status = status;
+ p_rcb->shdl = shdl;
+ p_rcb->lidx = lidx;
+ p_rcb->peer_features = 0;
+ if(lidx == (BTA_AV_NUM_LINKS + 1))
+ {
+ /* this LIDX is reserved for the AVRCP ACP connection */
+ p_cb->rc_acp_handle = p_rcb->handle;
+ p_cb->rc_acp_idx = (i + 1);
+ APPL_TRACE_DEBUG2("rc_acp_handle:%d idx:%d", p_cb->rc_acp_handle, p_cb->rc_acp_idx);
+ }
+ APPL_TRACE_DEBUG6("create %d, role: %d, shdl:%d, rc_handle:%d, lidx:%d, status:0x%x",
+ i, role, shdl, p_rcb->handle, lidx, p_rcb->status);
+
+ return rc_handle;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_valid_group_navi_msg
+**
+** Description Check if it is Group Navigation Msg for Metadata
+**
+** Returns BTA_AV_RSP_ACCEPT or BTA_AV_RSP_NOT_IMPL.
+**
+*******************************************************************************/
+static tBTA_AV_CODE bta_av_group_navi_supported(UINT8 len, UINT8 *p_data)
+{
+ tBTA_AV_CODE ret=BTA_AV_RSP_NOT_IMPL;
+ UINT8 *p_ptr = p_data;
+ UINT16 u16;
+ UINT32 u32;
+
+ if (p_bta_av_cfg->avrc_group && len == BTA_GROUP_NAVI_MSG_OP_DATA_LEN)
+ {
+ BTA_AV_BE_STREAM_TO_CO_ID(u32, p_ptr);
+ BE_STREAM_TO_UINT16(u16, p_ptr);
+
+ if (u32 == AVRC_CO_METADATA)
+ {
+ if (u16 <= AVRC_PDU_PREV_GROUP)
+ ret = BTA_AV_RSP_ACCEPT;
+ else
+ ret = BTA_AV_RSP_REJ;
+ }
+ }
+
+ return ret;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_op_supported
+**
+** Description Check if remote control operation is supported.
+**
+** Returns BTA_AV_RSP_ACCEPT of supported, BTA_AV_RSP_NOT_IMPL if not.
+**
+*******************************************************************************/
+static tBTA_AV_CODE bta_av_op_supported(tBTA_AV_RC rc_id)
+{
+ tBTA_AV_CODE ret_code = BTA_AV_RSP_NOT_IMPL;
+
+ if (p_bta_av_rc_id)
+ {
+ if (p_bta_av_rc_id[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+ {
+ ret_code = BTA_AV_RSP_ACCEPT;
+ }
+ else if ((p_bta_av_cfg->rc_pass_rsp == BTA_AV_RSP_INTERIM) && p_bta_av_rc_id_ac)
+ {
+ if (p_bta_av_rc_id_ac[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+ {
+ ret_code = BTA_AV_RSP_INTERIM;
+ }
+ }
+ }
+ return ret_code;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_find_lcb
+**
+** Description Given BD_addr, find the associated LCB.
+**
+** Returns NULL, if not found.
+**
+*******************************************************************************/
+tBTA_AV_LCB * bta_av_find_lcb(BD_ADDR addr, UINT8 op)
+{
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ int xx;
+ UINT8 mask;
+ tBTA_AV_LCB *p_lcb = NULL;
+
+ for(xx=0; xx<BTA_AV_NUM_LINKS; xx++)
+ {
+ mask = 1 << xx; /* the used mask for this lcb */
+ if((mask & p_cb->conn_lcb) && 0 ==( bdcmp(p_cb->lcb[xx].addr, addr)))
+ {
+ p_lcb = &p_cb->lcb[xx];
+ if(op == BTA_AV_LCB_FREE)
+ {
+ p_cb->conn_lcb &= ~mask; /* clear the connect mask */
+ APPL_TRACE_DEBUG1("conn_lcb: 0x%x", p_cb->conn_lcb);
+ }
+ break;
+ }
+ }
+ return p_lcb;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_opened
+**
+** Description Set AVRCP state to opened.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RC_OPEN rc_open;
+ tBTA_AV_SCB *p_scb;
+ int i;
+ UINT8 shdl = 0;
+ tBTA_AV_LCB *p_lcb;
+ tBTA_AV_RCB *p_rcb;
+ UINT8 tmp;
+ UINT8 disc = 0;
+
+ /* find the SCB & stop the timer */
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scb = p_cb->p_scb[i];
+ if(p_scb && bdcmp(p_scb->peer_addr, p_data->rc_conn_chg.peer_addr) == 0)
+ {
+ p_scb->rc_handle = p_data->rc_conn_chg.handle;
+ APPL_TRACE_DEBUG2("bta_av_rc_opened shdl:%d, srch %d", i + 1, p_scb->rc_handle);
+ shdl = i+1;
+ APPL_TRACE_ERROR1("use_rc:%d", p_scb->use_rc);
+ bta_sys_stop_timer(&p_scb->timer);
+ disc = p_scb->hndl;
+ break;
+ }
+ }
+
+ i = p_data->rc_conn_chg.handle;
+ if (p_cb->rcb[i].handle == BTA_AV_RC_HANDLE_NONE)
+ {
+ APPL_TRACE_ERROR1("not a valid handle:%d any more", i);
+ return;
+ }
+
+
+ if (p_cb->rcb[i].lidx == (BTA_AV_NUM_LINKS + 1) && shdl != 0)
+ {
+ /* rc is opened on the RC only ACP channel, but is for a specific
+ * SCB -> need to switch RCBs */
+ p_rcb = bta_av_get_rcb_by_shdl(shdl);
+ if (p_rcb)
+ {
+ p_rcb->shdl = p_cb->rcb[i].shdl;
+ tmp = p_rcb->lidx;
+ p_rcb->lidx = p_cb->rcb[i].lidx;
+ p_cb->rcb[i].lidx = tmp;
+ p_cb->rc_acp_handle = p_rcb->handle;
+ p_cb->rc_acp_idx = (p_rcb - p_cb->rcb) + 1;
+ APPL_TRACE_DEBUG2("switching RCB rc_acp_handle:%d idx:%d",
+ p_cb->rc_acp_handle, p_cb->rc_acp_idx);
+ }
+ }
+
+ p_cb->rcb[i].shdl = shdl;
+ rc_open.rc_handle = i;
+ APPL_TRACE_ERROR4("bta_av_rc_opened rcb[%d] shdl:%d lidx:%d/%d",
+ i, shdl, p_cb->rcb[i].lidx, p_cb->lcb[BTA_AV_NUM_LINKS].lidx);
+ p_cb->rcb[i].status |= BTA_AV_RC_CONN_MASK;
+
+ if(!shdl && 0 == p_cb->lcb[BTA_AV_NUM_LINKS].lidx)
+ {
+ /* no associated SCB -> connected to an RC only device
+ * update the index to the extra LCB */
+ p_lcb = &p_cb->lcb[BTA_AV_NUM_LINKS];
+ bdcpy(p_lcb->addr, p_data->rc_conn_chg.peer_addr);
+ APPL_TRACE_DEBUG6("rc_only bd_addr:%02x-%02x-%02x-%02x-%02x-%02x",
+ p_lcb->addr[0], p_lcb->addr[1],
+ p_lcb->addr[2], p_lcb->addr[3],
+ p_lcb->addr[4], p_lcb->addr[5]);
+ p_lcb->lidx = BTA_AV_NUM_LINKS + 1;
+ p_cb->rcb[i].lidx = p_lcb->lidx;
+ p_lcb->conn_msk = 1;
+ APPL_TRACE_ERROR3("rcb[%d].lidx=%d, lcb.conn_msk=x%x",
+ i, p_cb->rcb[i].lidx, p_lcb->conn_msk);
+ disc = p_data->rc_conn_chg.handle|BTA_AV_CHNL_MSK;
+ }
+
+ bdcpy(rc_open.peer_addr, p_data->rc_conn_chg.peer_addr);
+ rc_open.peer_features = p_cb->rcb[i].peer_features;
+ rc_open.status = BTA_AV_SUCCESS;
+ APPL_TRACE_DEBUG2("local features:x%x peer_features:x%x", p_cb->features,
+ rc_open.peer_features);
+ if(rc_open.peer_features == 0)
+ {
+ /* we have not done SDP on peer RC capabilities.
+ * peer must have initiated the RC connection */
+ rc_open.peer_features = BTA_AV_FEAT_RCCT;
+ bta_av_rc_disc(disc);
+ }
+ (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_av_rc_remote_cmd
+**
+** Description Send an AVRCP remote control command.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_remote_cmd(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RCB *p_rcb;
+ if (p_cb->features & BTA_AV_FEAT_RCCT)
+ {
+ if(p_data->hdr.layer_specific < BTA_AV_NUM_RCB)
+ {
+ p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
+ if(p_rcb->status & BTA_AV_RC_CONN_MASK)
+ {
+ AVRC_PassCmd(p_rcb->handle, p_data->api_remote_cmd.label,
+ &p_data->api_remote_cmd.msg);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_vendor_cmd
+**
+** Description Send an AVRCP vendor specific command.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_vendor_cmd(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RCB *p_rcb;
+ if ( (p_cb->features & (BTA_AV_FEAT_RCCT | BTA_AV_FEAT_VENDOR)) ==
+ (BTA_AV_FEAT_RCCT | BTA_AV_FEAT_VENDOR))
+ {
+ if(p_data->hdr.layer_specific < BTA_AV_NUM_RCB)
+ {
+ p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
+ AVRC_VendorCmd(p_rcb->handle, p_data->api_vendor.label, &p_data->api_vendor.msg);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_vendor_rsp
+**
+** Description Send an AVRCP vendor specific response.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_vendor_rsp(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RCB *p_rcb;
+ if ( (p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_VENDOR)) ==
+ (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_VENDOR))
+ {
+ if(p_data->hdr.layer_specific < BTA_AV_NUM_RCB)
+ {
+ p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
+ AVRC_VendorRsp(p_rcb->handle, p_data->api_vendor.label, &p_data->api_vendor.msg);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_meta_rsp
+**
+** Description Send an AVRCP metadata/advanced control command/response.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_meta_rsp(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_RCB *p_rcb;
+ BOOLEAN free = TRUE;
+
+ if ((p_cb->features & BTA_AV_FEAT_METADATA) && (p_data->hdr.layer_specific < BTA_AV_NUM_RCB))
+ {
+ if ((p_data->api_meta_rsp.is_rsp && (p_cb->features & BTA_AV_FEAT_RCTG)) ||
+ (!p_data->api_meta_rsp.is_rsp && (p_cb->features & BTA_AV_FEAT_RCCT)) )
+ {
+ p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
+ AVRC_MsgReq(p_rcb->handle, p_data->api_meta_rsp.label, p_data->api_meta_rsp.rsp_code,
+ p_data->api_meta_rsp.p_pkt);
+ free = FALSE;
+ }
+ }
+
+ if (free)
+ GKI_freebuf (p_data->api_meta_rsp.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_free_rsp
+**
+** Description free an AVRCP metadata command buffer.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_free_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ GKI_freebuf (p_data->api_meta_rsp.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_meta_req
+**
+** Description Send an AVRCP metadata command.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_free_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_av_chk_notif_evt_id
+**
+** Description make sure the requested player id is valid.
+**
+** Returns BTA_AV_STS_NO_RSP, if no error
+**
+*******************************************************************************/
+static tAVRC_STS bta_av_chk_notif_evt_id(tAVRC_MSG_VENDOR *p_vendor)
+{
+ tAVRC_STS status = BTA_AV_STS_NO_RSP;
+ UINT8 xx;
+ UINT16 u16;
+ UINT8 *p = p_vendor->p_vendor_data + 2;
+
+ BE_STREAM_TO_UINT16 (u16, p);
+ /* double check the fixed length */
+ if ((u16 != 5) || (p_vendor->vendor_len != 9))
+ {
+ status = AVRC_STS_INTERNAL_ERR;
+ }
+ else
+ {
+ /* make sure the player_id is valid */
+ for (xx=0; xx<p_bta_av_cfg->num_evt_ids; xx++)
+ {
+ if (*p == p_bta_av_cfg->p_meta_evt_ids[xx])
+ {
+ break;
+ }
+ }
+ if (xx == p_bta_av_cfg->num_evt_ids)
+ {
+ status = AVRC_STS_BAD_PARAM;
+ }
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_proc_meta_cmd
+**
+** Description Process an AVRCP metadata command from the peer.
+**
+** Returns TRUE to respond immediately
+**
+*******************************************************************************/
+tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE *p_rc_rsp, tBTA_AV_RC_MSG *p_msg, UINT8 *p_ctype)
+{
+ tBTA_AV_EVT evt = BTA_AV_META_MSG_EVT;
+ UINT8 u8, pdu, *p;
+ UINT16 u16;
+ tAVRC_MSG_VENDOR *p_vendor = &p_msg->msg.vendor;
+
+ pdu = *(p_vendor->p_vendor_data);
+ p_rc_rsp->pdu = pdu;
+ *p_ctype = AVRC_RSP_REJ;
+ /* Metadata messages only use PANEL sub-unit type */
+ if (p_vendor->hdr.subunit_type != AVRC_SUB_PANEL)
+ {
+ APPL_TRACE_DEBUG0("SUBUNIT must be PANEL");
+ /* reject it */
+ evt=0;
+ p_vendor->hdr.ctype = BTA_AV_RSP_NOT_IMPL;
+ AVRC_VendorRsp(p_msg->handle, p_msg->label, &p_msg->msg.vendor);
+ }
+ else
+ {
+ switch (pdu)
+ {
+ case AVRC_PDU_GET_CAPABILITIES:
+ /* process GetCapabilities command without reporting the event to app */
+ evt = 0;
+ u8 = *(p_vendor->p_vendor_data + 4);
+ p = p_vendor->p_vendor_data + 2;
+ p_rc_rsp->get_caps.capability_id = u8;
+ BE_STREAM_TO_UINT16 (u16, p);
+ if ((u16 != 1) || (p_vendor->vendor_len != 5))
+ {
+ p_rc_rsp->get_caps.status = AVRC_STS_INTERNAL_ERR;
+ }
+ else
+ {
+ p_rc_rsp->get_caps.status = AVRC_STS_NO_ERROR;
+ if (u8 == AVRC_CAP_COMPANY_ID)
+ {
+ *p_ctype = AVRC_RSP_IMPL_STBL;
+ p_rc_rsp->get_caps.count = p_bta_av_cfg->num_co_ids;
+ memcpy(p_rc_rsp->get_caps.param.company_id, p_bta_av_cfg->p_meta_co_ids,
+ (p_bta_av_cfg->num_co_ids << 2));
+ }
+ else if (u8 == AVRC_CAP_EVENTS_SUPPORTED)
+ {
+ *p_ctype = AVRC_RSP_IMPL_STBL;
+ p_rc_rsp->get_caps.count = p_bta_av_cfg->num_evt_ids;
+ memcpy(p_rc_rsp->get_caps.param.event_id, p_bta_av_cfg->p_meta_evt_ids,
+ p_bta_av_cfg->num_evt_ids);
+ }
+ else
+ {
+ APPL_TRACE_DEBUG1("Invalid capability ID: 0x%x", u8);
+ /* reject - unknown capability ID */
+ p_rc_rsp->get_caps.status = AVRC_STS_BAD_PARAM;
+ }
+ }
+ break;
+
+
+ case AVRC_PDU_REGISTER_NOTIFICATION:
+ /* make sure the event_id is implemented */
+ p_rc_rsp->rsp.status = bta_av_chk_notif_evt_id (p_vendor);
+ if (p_rc_rsp->rsp.status != BTA_AV_STS_NO_RSP)
+ evt = 0;
+ break;
+
+ }
+ }
+
+ return evt;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_av_rc_msg
+**
+** Description Process an AVRCP message from the peer.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_EVT evt = 0;
+ tBTA_AV av;
+ BT_HDR *p_pkt = NULL;
+ tAVRC_MSG_VENDOR *p_vendor = &p_data->rc_msg.msg.vendor;
+
+ if (p_data->rc_msg.opcode == AVRC_OP_PASS_THRU)
+ {
+ /* if this is a pass thru command */
+ if (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_CTRL)
+ {
+ /* check if operation is supported */
+ if (p_data->rc_msg.msg.pass.op_id == AVRC_ID_VENDOR)
+ {
+ p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_NOT_IMPL;
+ }
+ else
+ {
+ p_data->rc_msg.msg.hdr.ctype = bta_av_op_supported(p_data->rc_msg.msg.pass.op_id);
+ }
+
+ /* send response */
+ if (p_data->rc_msg.msg.hdr.ctype != BTA_AV_RSP_INTERIM)
+ AVRC_PassRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.pass);
+
+ /* set up for callback if supported */
+ if (p_data->rc_msg.msg.hdr.ctype == BTA_AV_RSP_ACCEPT || p_data->rc_msg.msg.hdr.ctype == BTA_AV_RSP_INTERIM)
+ {
+ evt = BTA_AV_REMOTE_CMD_EVT;
+ av.remote_cmd.rc_id = p_data->rc_msg.msg.pass.op_id;
+ av.remote_cmd.key_state = p_data->rc_msg.msg.pass.state;
+ av.remote_cmd.p_data = p_data->rc_msg.msg.pass.p_pass_data;
+ av.remote_cmd.len = p_data->rc_msg.msg.pass.pass_len;
+ memcpy(&av.remote_cmd.hdr, &p_data->rc_msg.msg.hdr, sizeof (tAVRC_HDR));
+ av.remote_cmd.label = p_data->rc_msg.label;
+ }
+ }
+ /* else if this is a pass thru response */
+ else if (p_data->rc_msg.msg.hdr.ctype >= AVRC_RSP_ACCEPT)
+ {
+ /* set up for callback */
+ evt = BTA_AV_REMOTE_RSP_EVT;
+ av.remote_rsp.rc_id = p_data->rc_msg.msg.pass.op_id;
+ av.remote_rsp.key_state = p_data->rc_msg.msg.pass.state;
+ av.remote_rsp.rsp_code = p_data->rc_msg.msg.hdr.ctype;
+ av.remote_rsp.label = p_data->rc_msg.label;
+ }
+ /* must be a bad ctype -> reject*/
+ else
+ {
+ p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_REJ;
+ AVRC_PassRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.pass);
+ }
+ }
+ /* else if this is a vendor specific command or response */
+ else if (p_data->rc_msg.opcode == AVRC_OP_VENDOR)
+ {
+ /* set up for callback */
+ av.vendor_cmd.code = p_data->rc_msg.msg.hdr.ctype;
+ av.vendor_cmd.company_id = p_vendor->company_id;
+ av.vendor_cmd.label = p_data->rc_msg.label;
+ av.vendor_cmd.p_data = p_vendor->p_vendor_data;
+ av.vendor_cmd.len = p_vendor->vendor_len;
+
+ /* if configured to support vendor specific and it's a command */
+ if ((p_cb->features & BTA_AV_FEAT_VENDOR) &&
+ p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ)
+ {
+ evt = BTA_AV_VENDOR_CMD_EVT;
+ }
+ /* else if configured to support vendor specific and it's a response */
+ else if ((p_cb->features & BTA_AV_FEAT_VENDOR) &&
+ p_data->rc_msg.msg.hdr.ctype >= AVRC_RSP_ACCEPT)
+ {
+ evt = BTA_AV_VENDOR_RSP_EVT;
+
+ }
+ /* else if not configured to support vendor specific and it's a command */
+ else if (!(p_cb->features & BTA_AV_FEAT_VENDOR) &&
+ p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ)
+ {
+ if(p_data->rc_msg.msg.vendor.p_vendor_data[0] == AVRC_PDU_INVALID)
+ {
+ /* reject it */
+ p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_REJ;
+ p_data->rc_msg.msg.vendor.p_vendor_data[4] = AVRC_STS_BAD_CMD;
+ }
+ else
+ p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_NOT_IMPL;
+ AVRC_VendorRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.vendor);
+ }
+ }
+
+ /* call callback */
+ if (evt != 0)
+ {
+ av.remote_cmd.rc_handle = p_data->rc_msg.handle;
+ (*p_cb->p_cback)(evt, &av);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_close
+**
+** Description close the specified AVRC handle.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_close (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ UINT16 handle = p_data->hdr.layer_specific;
+ tBTA_AV_SCB *p_scb;
+ tBTA_AV_RCB *p_rcb;
+
+ if(handle < BTA_AV_NUM_RCB)
+ {
+ p_rcb = &p_cb->rcb[handle];
+
+ APPL_TRACE_DEBUG2("bta_av_rc_close handle: %d, status=0x%x", p_rcb->handle, p_rcb->status);
+ if(p_rcb->handle != BTA_AV_RC_HANDLE_NONE)
+ {
+ if(p_rcb->shdl)
+ {
+ p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
+ if(p_scb)
+ {
+ /* just in case the RC timer is active
+ if(bta_av_cb.features & BTA_AV_FEAT_RCCT &&
+ p_scb->chnl == BTA_AV_CHNL_AUDIO) */
+ bta_sys_stop_timer(&p_scb->timer);
+ }
+ }
+
+ AVRC_Close(p_rcb->handle);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_get_shdl
+**
+** Returns The index to p_scb[]
+**
+*******************************************************************************/
+static UINT8 bta_av_get_shdl(tBTA_AV_SCB *p_scb)
+{
+ int i;
+ UINT8 shdl = 0;
+ /* find the SCB & stop the timer */
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ if(p_scb == bta_av_cb.p_scb[i])
+ {
+ shdl = i+1;
+ break;
+ }
+ }
+ return shdl;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_stream_chg
+**
+** Description audio streaming status changed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_stream_chg(tBTA_AV_SCB *p_scb, BOOLEAN started)
+{
+ UINT8 started_msk;
+ int i;
+ UINT8 *p_streams;
+ BOOLEAN no_streams = FALSE;
+ tBTA_AV_SCB *p_scbi;
+
+ started_msk = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+ APPL_TRACE_DEBUG3 ("bta_av_stream_chg started:%d started_msk:x%x chnl:x%x", started,
+ started_msk, p_scb->chnl);
+ if (BTA_AV_CHNL_AUDIO == p_scb->chnl)
+ p_streams = &bta_av_cb.audio_streams;
+ else
+ p_streams = &bta_av_cb.video_streams;
+
+ if (started)
+ {
+ /* Let L2CAP know this channel is processed with high priority */
+ L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_HIGH);
+ (*p_streams) |= started_msk;
+ }
+ else
+ {
+ (*p_streams) &= ~started_msk;
+ }
+
+ if (!started)
+ {
+ i=0;
+ if (BTA_AV_CHNL_AUDIO == p_scb->chnl)
+ {
+ if (bta_av_cb.video_streams == 0)
+ no_streams = TRUE;
+ }
+ else
+ {
+ no_streams = TRUE;
+ if ( bta_av_cb.audio_streams )
+ {
+ for (; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scbi = bta_av_cb.p_scb[i];
+ /* scb is used and started */
+ if ( p_scbi && (bta_av_cb.audio_streams & BTA_AV_HNDL_TO_MSK(i))
+ && bdcmp(p_scbi->peer_addr, p_scb->peer_addr) == 0)
+ {
+ no_streams = FALSE;
+ break;
+ }
+ }
+
+ }
+ }
+
+ APPL_TRACE_DEBUG4 ("no_streams:%d i:%d, audio_streams:x%x, video_streams:x%x", no_streams, i,
+ bta_av_cb.audio_streams, bta_av_cb.video_streams);
+ if (no_streams)
+ {
+ /* Let L2CAP know this channel is processed with low priority */
+ L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_NORMAL);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_av_conn_chg
+**
+** Description connetion status changed.
+** Open an AVRCP acceptor channel, if new conn.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_conn_chg(tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ tBTA_AV_SCB *p_scb;
+ tBTA_AV_SCB *p_scbi;
+ UINT8 mask;
+ UINT8 conn_msk;
+ UINT8 old_msk;
+ int i;
+ int index = (p_data->hdr.layer_specific & BTA_AV_HNDL_MSK) - 1;
+ tBTA_AV_LCB *p_lcb;
+ tBTA_AV_LCB *p_lcb_rc;
+ tBTA_AV_RCB *p_rcb, *p_rcb2;
+ BOOLEAN chk_restore = FALSE;
+
+ p_scb = p_cb->p_scb[index];
+
+ mask = BTA_AV_HNDL_TO_MSK(index);
+ p_lcb = bta_av_find_lcb(p_data->conn_chg.peer_addr, BTA_AV_LCB_FIND);
+ conn_msk = 1 << (index + 1);
+ if(p_data->conn_chg.is_up)
+ {
+ /* set the conned mask for this channel */
+ if(p_scb)
+ {
+ if(p_lcb)
+ {
+ p_lcb->conn_msk |= conn_msk;
+ for (i=0; i<BTA_AV_NUM_RCB; i++)
+ {
+ if (bta_av_cb.rcb[i].lidx == p_lcb->lidx)
+ {
+ bta_av_cb.rcb[i].shdl = index + 1;
+ APPL_TRACE_DEBUG5("conn_chg up[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i,
+ bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
+ bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx);
+ break;
+ }
+ }
+ }
+ if (p_scb->chnl == BTA_AV_CHNL_AUDIO)
+ {
+ old_msk = p_cb->conn_audio;
+ p_cb->conn_audio |= mask;
+ }
+ else
+ {
+ old_msk = p_cb->conn_video;
+ p_cb->conn_video |= mask;
+ }
+
+ if ((old_msk & mask) == 0)
+ {
+ /* increase the audio open count, if not set yet */
+ bta_av_cb.audio_open_cnt++;
+ }
+
+
+ APPL_TRACE_DEBUG2("rc_acp_handle:%d rc_acp_idx:%d", p_cb->rc_acp_handle, p_cb->rc_acp_idx);
+ /* check if the AVRCP ACP channel is already connected */
+ if(p_lcb && p_cb->rc_acp_handle != BTA_AV_RC_HANDLE_NONE && p_cb->rc_acp_idx)
+ {
+ p_lcb_rc = &p_cb->lcb[BTA_AV_NUM_LINKS];
+ APPL_TRACE_DEBUG1("rc_acp is connected && conn_chg on same addr p_lcb_rc->conn_msk:x%x",
+ p_lcb_rc->conn_msk);
+ /* check if the RC is connected to the scb addr */
+ APPL_TRACE_DEBUG6 ("p_lcb_rc->addr: %02x:%02x:%02x:%02x:%02x:%02x",
+ p_lcb_rc->addr[0], p_lcb_rc->addr[1], p_lcb_rc->addr[2], p_lcb_rc->addr[3],
+ p_lcb_rc->addr[4], p_lcb_rc->addr[5]);
+ APPL_TRACE_DEBUG6 ("conn_chg.peer_addr: %02x:%02x:%02x:%02x:%02x:%02x",
+ p_data->conn_chg.peer_addr[0], p_data->conn_chg.peer_addr[1],
+ p_data->conn_chg.peer_addr[2],
+ p_data->conn_chg.peer_addr[3], p_data->conn_chg.peer_addr[4],
+ p_data->conn_chg.peer_addr[5]);
+ if (p_lcb_rc->conn_msk && bdcmp(p_lcb_rc->addr, p_data->conn_chg.peer_addr) == 0)
+ {
+ /* AVRCP is already connected.
+ * need to update the association betwen SCB and RCB */
+ p_lcb_rc->conn_msk = 0; /* indicate RC ONLY is not connected */
+ p_lcb_rc->lidx = 0;
+ p_scb->rc_handle = p_cb->rc_acp_handle;
+ p_rcb = &p_cb->rcb[p_cb->rc_acp_idx - 1];
+ p_rcb->shdl = bta_av_get_shdl(p_scb);
+ APPL_TRACE_DEBUG3("update rc_acp shdl:%d/%d srch:%d", index + 1, p_rcb->shdl,
+ p_scb->rc_handle );
+
+ p_rcb2 = bta_av_get_rcb_by_shdl(p_rcb->shdl);
+ if (p_rcb2)
+ {
+ /* found the RCB that was created to associated with this SCB */
+ p_cb->rc_acp_handle = p_rcb2->handle;
+ p_cb->rc_acp_idx = (p_rcb2 - p_cb->rcb) + 1;
+ APPL_TRACE_DEBUG2("new rc_acp_handle:%d, idx:%d", p_cb->rc_acp_handle,
+ p_cb->rc_acp_idx);
+ p_rcb2->lidx = (BTA_AV_NUM_LINKS + 1);
+ APPL_TRACE_DEBUG3("rc2 handle:%d lidx:%d/%d",p_rcb2->handle, p_rcb2->lidx,
+ p_cb->lcb[p_rcb2->lidx-1].lidx);
+ }
+ p_rcb->lidx = p_lcb->lidx;
+ APPL_TRACE_DEBUG3("rc handle:%d lidx:%d/%d",p_rcb->handle, p_rcb->lidx,
+ p_cb->lcb[p_rcb->lidx-1].lidx);
+ }
+ }
+ }
+ }
+ else
+ {
+ if ((p_cb->conn_audio & mask) && bta_av_cb.audio_open_cnt)
+ {
+ /* this channel is still marked as open. decrease the count */
+ bta_av_cb.audio_open_cnt--;
+ }
+
+ /* clear the conned mask for this channel */
+ p_cb->conn_audio &= ~mask;
+ p_cb->conn_video &= ~mask;
+ if(p_scb)
+ {
+ /* the stream is closed.
+ * clear the peer address, so it would not mess up the AVRCP for the next round of operation */
+ bdcpy(p_scb->peer_addr, bd_addr_null);
+ if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
+ {
+ if(p_lcb)
+ {
+ p_lcb->conn_msk &= ~conn_msk;
+ }
+ /* audio channel is down. make sure the INT channel is down */
+ /* just in case the RC timer is active
+ if(p_cb->features & BTA_AV_FEAT_RCCT) */
+ {
+ bta_sys_stop_timer(&p_scb->timer);
+ }
+ /* one audio channel goes down. check if we need to restore high priority */
+ chk_restore = TRUE;
+ }
+ }
+
+ APPL_TRACE_DEBUG1("bta_av_conn_chg shdl:%d", index + 1);
+ for (i=0; i<BTA_AV_NUM_RCB; i++)
+ {
+ APPL_TRACE_DEBUG5("conn_chg dn[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i,
+ bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
+ bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx);
+ if(bta_av_cb.rcb[i].shdl == index + 1)
+ {
+ bta_av_del_rc(&bta_av_cb.rcb[i]);
+ break;
+ }
+ }
+
+ if(p_cb->conn_audio == 0 && p_cb->conn_video == 0)
+ {
+ /* if both channels are not connected,
+ * close all RC channels */
+ bta_av_close_all_rc(p_cb);
+ }
+
+ /* if the AVRCP is no longer listening, create the listening channel */
+ if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG)
+ bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+ }
+
+ APPL_TRACE_DEBUG6("bta_av_conn_chg audio:%x video:%x up:%d conn_msk:0x%x chk_restore:%d audio_open_cnt:%d",
+ p_cb->conn_audio, p_cb->conn_video, p_data->conn_chg.is_up, conn_msk, chk_restore, p_cb->audio_open_cnt);
+
+ if (chk_restore)
+ {
+ if (p_cb->audio_open_cnt == 1)
+ {
+ /* one audio channel goes down and there's one audio channel remains open.
+ * restore the switch role in default link policy */
+ bta_sys_set_default_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH);
+ /* allow role switch, if this is the last connection */
+ bta_av_restore_switch();
+ }
+ if (p_cb->audio_open_cnt)
+ {
+ /* adjust flush timeout settings to longer period */
+ for (i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scbi = bta_av_cb.p_scb[i];
+ if (p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started)
+ {
+ /* may need to update the flush timeout of this already started stream */
+ if (p_scbi->co_started != bta_av_cb.audio_open_cnt)
+ {
+ p_scbi->co_started = bta_av_cb.audio_open_cnt;
+ L2CA_SetFlushTimeout(p_scbi->peer_addr, p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1] );
+ }
+ }
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_disable
+**
+** Description disable AV.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_disable(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+ BT_HDR hdr;
+ UINT16 xx;
+
+ p_cb->disabling = TRUE;
+
+ bta_av_close_all_rc(p_cb);
+
+ utl_freebuf((void **) &p_cb->p_disc_db);
+
+ /* disable audio/video - de-register all channels,
+ * expect BTA_AV_DEREG_COMP_EVT when deregister is complete */
+ for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+ {
+ hdr.layer_specific = xx + 1;
+ bta_av_api_deregister((tBTA_AV_DATA *)&hdr);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_api_disconnect
+**
+** Description .
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_api_disconnect(tBTA_AV_DATA *p_data)
+{
+ AVDT_DisconnectReq(p_data->api_discnt.bd_addr, bta_av_conn_cback);
+ bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sig_chg
+**
+** Description process AVDT signal channel up/down.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_sig_chg(tBTA_AV_DATA *p_data)
+{
+ UINT16 event = p_data->str_msg.hdr.layer_specific;
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ int xx;
+ UINT8 mask;
+ tBTA_AV_LCB *p_lcb = NULL;
+
+ APPL_TRACE_DEBUG1("bta_av_sig_chg event: %d", event);
+ if(event == AVDT_CONNECT_IND_EVT)
+ {
+ p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FIND);
+ if(!p_lcb)
+ {
+ /* if the address does not have an LCB yet, alloc one */
+ for(xx=0; xx<BTA_AV_NUM_LINKS; xx++)
+ {
+ mask = 1 << xx;
+ APPL_TRACE_DEBUG1("conn_lcb: 0x%x", p_cb->conn_lcb);
+ if(!(mask & p_cb->conn_lcb))
+ {
+ if (!p_cb->p_scb[xx])
+ {
+ /* We do not have scb for this avdt connection. */
+ /* Silently close the connection. */
+ APPL_TRACE_ERROR0("av scb not available for avdt connection");
+ AVDT_DisconnectReq (p_data->str_msg.bd_addr, NULL);
+ return;
+ }
+
+ p_lcb = &p_cb->lcb[xx];
+ p_lcb->lidx = xx + 1;
+ bdcpy(p_lcb->addr, p_data->str_msg.bd_addr);
+ p_lcb->conn_msk = 0; /* clear the connect mask */
+ /* start listening when the signal channel is open */
+ if (p_cb->features & BTA_AV_FEAT_RCTG)
+ {
+ bta_av_rc_create(p_cb, AVCT_ACP, 0, p_lcb->lidx);
+ }
+ /* this entry is not used yet. */
+ p_cb->conn_lcb |= mask; /* mark it as used */
+ APPL_TRACE_DEBUG1("start sig timer %d", p_data->hdr.offset);
+ if (p_data->hdr.offset == AVDT_ACP)
+ {
+ APPL_TRACE_DEBUG1("Incoming L2CAP acquired, set state as incoming", NULL);
+ bdcpy(p_cb->p_scb[xx]->peer_addr, p_data->str_msg.bd_addr);
+ p_cb->p_scb[xx]->use_rc = TRUE; /* allowing RC for incoming connection */
+ bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_ACP_CONNECT_EVT, p_data);
+
+ /* The Pending Event should be sent as soon as the L2CAP signalling channel
+ * is set up, which is NOW. Earlier this was done only after
+ * BTA_AV_SIG_TIME_VAL milliseconds.
+ * The following function shall send the event and start the recurring timer
+ */
+ bta_av_sig_timer(NULL);
+
+ /* Possible collision : need to avoid outgoing processing while the timer is running */
+ p_cb->p_scb[xx]->coll_mask = BTA_AV_COLL_INC_TMR;
+
+ p_cb->acp_sig_tmr.param = (UINT32)xx;
+ p_cb->acp_sig_tmr.p_cback = (TIMER_CBACK*)&bta_av_acp_sig_timer_cback;
+ bta_sys_start_timer(&p_cb->acp_sig_tmr, 0, BTA_AV_ACP_SIG_TIME_VAL);
+ }
+ break;
+ }
+ }
+ }
+ }
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+ else if (event == BTA_AR_AVDT_CONN_EVT)
+ {
+ bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+ }
+#endif
+ else
+ {
+ /* disconnected. */
+ p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FREE);
+ if(p_lcb && p_lcb->conn_msk)
+ {
+ APPL_TRACE_DEBUG1("conn_msk: 0x%x", p_lcb->conn_msk);
+ /* clean up ssm */
+ for(xx=0; xx < BTA_AV_NUM_STRS; xx++)
+ {
+ mask = 1 << (xx + 1);
+ if ((mask & p_lcb->conn_msk) && (p_cb->p_scb[xx]) &&
+ (bdcmp(p_cb->p_scb[xx]->peer_addr, p_data->str_msg.bd_addr) == 0))
+ {
+ bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_AVDT_DISCONNECT_EVT, NULL);
+ }
+ }
+ }
+ }
+ APPL_TRACE_DEBUG1("conn_lcb: 0x%x", p_cb->conn_lcb);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sig_timer
+**
+** Description process the signal channel timer. This timer is started
+** when the AVDTP signal channel is connected. If no profile
+** is connected, the timer goes off every BTA_AV_SIG_TIME_VAL
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_sig_timer(tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ int xx;
+ UINT8 mask;
+ tBTA_AV_LCB *p_lcb = NULL;
+ tBTA_AV_PEND pend;
+
+ APPL_TRACE_DEBUG0("bta_av_sig_timer");
+ for(xx=0; xx<BTA_AV_NUM_LINKS; xx++)
+ {
+ mask = 1 << xx;
+ if(mask & p_cb->conn_lcb)
+ {
+ /* this entry is used. check if it is connected */
+ p_lcb = &p_cb->lcb[xx];
+ if(!p_lcb->conn_msk)
+ {
+ bta_sys_start_timer(&p_cb->sig_tmr, BTA_AV_SIG_TIMER_EVT, BTA_AV_SIG_TIME_VAL);
+ bdcpy(pend.bd_addr, p_lcb->addr);
+ (*p_cb->p_cback)(BTA_AV_PENDING_EVT, (tBTA_AV *) &pend);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_acp_sig_timer_cback
+**
+** Description Process the timeout when SRC is accepting connection
+** and SNK did not start signalling.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+ UINT8 inx = (UINT8)p_tle->param;
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ tBTA_AV_SCB *p_scb = p_cb->p_scb[inx];
+ tBTA_AV_API_OPEN *p_buf;
+
+ if (p_scb)
+ {
+ APPL_TRACE_DEBUG1("bta_av_acp_sig_timer_cback, coll_mask = 0x%02X", p_scb->coll_mask);
+
+ if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR)
+ {
+ p_scb->coll_mask &= ~BTA_AV_COLL_INC_TMR;
+
+ if (bta_av_is_scb_opening(p_scb))
+ {
+ if (p_scb->p_disc_db)
+ {
+ /* We are still doing SDP. Run the timer again. */
+ p_scb->coll_mask |= BTA_AV_COLL_INC_TMR;
+
+ p_cb->acp_sig_tmr.param = (UINT32)inx;
+ p_cb->acp_sig_tmr.p_cback = (TIMER_CBACK *)&bta_av_acp_sig_timer_cback;
+ bta_sys_start_timer(&p_cb->acp_sig_tmr, 0, BTA_AV_ACP_SIG_TIME_VAL);
+ }
+ else
+ {
+ /* SNK did not start signalling, resume signalling process. */
+ bta_av_discover_req (p_scb, NULL);
+ }
+ }
+ else if (bta_av_is_scb_incoming(p_scb))
+ {
+ /* Stay in incoming state if SNK does not start signalling */
+
+ /* API open was called right after SNK opened L2C connection. */
+ if (p_scb->coll_mask & BTA_AV_COLL_API_CALLED)
+ {
+ p_scb->coll_mask &= ~BTA_AV_COLL_API_CALLED;
+
+ /* BTA_AV_API_OPEN_EVT */
+ if ((p_buf = (tBTA_AV_API_OPEN *) GKI_getbuf(sizeof(tBTA_AV_API_OPEN))) != NULL)
+ {
+ memcpy(p_buf, &(p_scb->open_api), sizeof(tBTA_AV_API_OPEN));
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_check_peer_features
+**
+** Description checks
+**
+** Returns void
+**
+*******************************************************************************/
+tBTA_AV_FEAT bta_av_check_peer_features (UINT16 service_uuid)
+{
+ tBTA_AV_FEAT peer_features = 0;
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ tSDP_DISC_REC *p_rec = NULL;
+ tSDP_DISC_ATTR *p_attr;
+ UINT16 peer_rc_version=0;
+ UINT16 categories = 0;
+
+ APPL_TRACE_DEBUG1("bta_av_check_peer_features service_uuid:x%x", service_uuid);
+ /* loop through all records we found */
+ while (TRUE)
+ {
+ /* get next record; if none found, we're done */
+ if ((p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, p_rec)) == NULL)
+ {
+ break;
+ }
+
+ if (( SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_CLASS_ID_LIST)) != NULL)
+ {
+ /* find peer features */
+ if (SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL))
+ {
+ peer_features |= BTA_AV_FEAT_RCCT;
+ }
+ if (SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET, NULL))
+ {
+ peer_features |= BTA_AV_FEAT_RCTG;
+ }
+ }
+
+ if (( SDP_FindAttributeInRec(p_rec, ATTR_ID_BT_PROFILE_DESC_LIST)) != NULL)
+ {
+ /* get profile version (if failure, version parameter is not updated) */
+ SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_rc_version);
+ APPL_TRACE_DEBUG1("peer_rc_version 0x%x", peer_rc_version);
+
+ if (peer_rc_version >= AVRC_REV_1_3)
+ peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
+
+ if (peer_rc_version >= AVRC_REV_1_4)
+ {
+ peer_features |= (BTA_AV_FEAT_ADV_CTRL);
+ /* get supported categories */
+ if ((p_attr = SDP_FindAttributeInRec(p_rec,
+ ATTR_ID_SUPPORTED_FEATURES)) != NULL)
+ {
+ categories = p_attr->attr_value.v.u16;
+ if (categories & AVRC_SUPF_CT_BROWSE)
+ peer_features |= (BTA_AV_FEAT_BROWSE);
+ }
+ }
+ }
+ }
+ APPL_TRACE_DEBUG1("peer_features:x%x", peer_features);
+ return peer_features;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_disc_done
+**
+** Description Handle AVRCP service discovery results. If matching
+** service found, open AVRCP connection.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ tBTA_AV_SCB *p_scb = NULL;
+ tBTA_AV_LCB *p_lcb;
+ tBTA_AV_RC_OPEN rc_open;
+ tBTA_AV_RC_FEAT rc_feat;
+ UINT8 rc_handle;
+ tBTA_AV_FEAT peer_features; /* peer features mask */
+
+ APPL_TRACE_DEBUG1("bta_av_rc_disc_done disc:x%x", p_cb->disc);
+ if (!p_cb->disc)
+ {
+ return;
+ }
+
+ if ((p_cb->disc & BTA_AV_CHNL_MSK) == BTA_AV_CHNL_MSK)
+ {
+ /* this is the rc handle/index to tBTA_AV_RCB */
+ rc_handle = p_cb->disc & (~BTA_AV_CHNL_MSK);
+ }
+ else
+ {
+ p_scb = p_cb->p_scb[(p_cb->disc & BTA_AV_HNDL_MSK) - 1];
+ if (p_scb)
+ rc_handle = p_scb->rc_handle;
+ else
+ {
+ p_cb->disc = 0;
+ return;
+ }
+ }
+
+ APPL_TRACE_DEBUG1("rc_handle %d", rc_handle);
+ peer_features = bta_av_check_peer_features (UUID_SERVCLASS_AV_REMOTE_CONTROL);
+ if ((p_cb->features & BTA_AV_FEAT_ADV_CTRL) && ((peer_features&BTA_AV_FEAT_ADV_CTRL) == 0))
+ {
+ /* if we support advance control and peer does not, check their support on TG role
+ * some implementation uses 1.3 on CT ans 1.4 on TG */
+ peer_features |= bta_av_check_peer_features (UUID_SERVCLASS_AV_REM_CTRL_TARGET);
+ }
+
+ p_cb->disc = 0;
+ utl_freebuf((void **) &p_cb->p_disc_db);
+
+ APPL_TRACE_DEBUG2("peer_features 0x%x, features 0x%x", peer_features, p_cb->features);
+
+ /* if we have no rc connection */
+ if (rc_handle == BTA_AV_RC_HANDLE_NONE)
+ {
+ if (p_scb)
+ {
+ /* if peer remote control service matches ours and USE_RC is TRUE */
+ if ((((p_cb->features & BTA_AV_FEAT_RCCT) && (peer_features & BTA_AV_FEAT_RCTG)) ||
+ ((p_cb->features & BTA_AV_FEAT_RCTG) && (peer_features & BTA_AV_FEAT_RCCT))) )
+ {
+ p_lcb = bta_av_find_lcb(p_scb->peer_addr, BTA_AV_LCB_FIND);
+ if(p_lcb)
+ {
+ rc_handle = bta_av_rc_create(p_cb, AVCT_INT, (UINT8)(p_scb->hdi + 1), p_lcb->lidx);
+ p_cb->rcb[rc_handle].peer_features = peer_features;
+ }
+#if (BT_USE_TRACES == TRUE || BT_TRACE_APPL == TRUE)
+ else
+ {
+ APPL_TRACE_ERROR0("can not find LCB!!");
+ }
+#endif
+ }
+ else if(p_scb->use_rc)
+ {
+ /* can not find AVRC on peer device. report failure */
+ p_scb->use_rc = FALSE;
+ bdcpy(rc_open.peer_addr, p_scb->peer_addr);
+ rc_open.peer_features = 0;
+ rc_open.status = BTA_AV_FAIL_SDP;
+ (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
+ }
+ }
+ }
+ else
+ {
+ p_cb->rcb[rc_handle].peer_features = peer_features;
+ rc_feat.rc_handle = rc_handle;
+ rc_feat.peer_features = peer_features;
+ (*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, (tBTA_AV *) &rc_feat);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_closed
+**
+** Description Set AVRCP state to closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_closed(tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ tBTA_AV_RC_CLOSE rc_close;
+ tBTA_AV_RC_CONN_CHG *p_msg = (tBTA_AV_RC_CONN_CHG *)p_data;
+ tBTA_AV_RCB *p_rcb;
+ tBTA_AV_SCB *p_scb;
+ int i;
+ BOOLEAN conn = FALSE;
+ tBTA_AV_LCB *p_lcb;
+
+ rc_close.rc_handle = BTA_AV_RC_HANDLE_NONE;
+ APPL_TRACE_DEBUG1("bta_av_rc_closed rc_handle:%d", p_msg->handle);
+ for(i=0; i<BTA_AV_NUM_RCB; i++)
+ {
+ p_rcb = &p_cb->rcb[i];
+ APPL_TRACE_DEBUG3("bta_av_rc_closed rcb[%d] rc_handle:%d, status=0x%x", i, p_rcb->handle, p_rcb->status);
+ if(p_rcb->handle == p_msg->handle)
+ {
+ rc_close.rc_handle = i;
+ p_rcb->status &= ~BTA_AV_RC_CONN_MASK;
+ p_rcb->peer_features = 0;
+ APPL_TRACE_DEBUG2(" shdl:%d, lidx:%d", p_rcb->shdl, p_rcb->lidx);
+ if(p_rcb->shdl)
+ {
+ p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
+ if(p_scb)
+ {
+ bdcpy(rc_close.peer_addr, p_scb->peer_addr);
+ if(p_scb->rc_handle == p_rcb->handle)
+ p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
+ APPL_TRACE_DEBUG2("shdl:%d, srch:%d", p_rcb->shdl, p_scb->rc_handle);
+ }
+ p_rcb->shdl = 0;
+ }
+ else if(p_rcb->lidx == (BTA_AV_NUM_LINKS + 1) )
+ {
+ /* if the RCB uses the extra LCB, use the addr for event and clean it */
+ p_lcb = &p_cb->lcb[BTA_AV_NUM_LINKS];
+ bdcpy(rc_close.peer_addr, p_msg->peer_addr);
+ APPL_TRACE_DEBUG6("rc_only closed bd_addr:%02x-%02x-%02x-%02x-%02x-%02x",
+ p_msg->peer_addr[0], p_msg->peer_addr[1],
+ p_msg->peer_addr[2], p_msg->peer_addr[3],
+ p_msg->peer_addr[4], p_msg->peer_addr[5]);
+ p_lcb->conn_msk = 0;
+ p_lcb->lidx = 0;
+ }
+ p_rcb->lidx = 0;
+
+ if((p_rcb->status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)
+ {
+ /* AVCT CCB is deallocated */
+ p_rcb->handle = BTA_AV_RC_HANDLE_NONE;
+ p_rcb->status = 0;
+ }
+ else
+ {
+ /* AVCT CCB is still there. dealloc */
+ bta_av_del_rc(p_rcb);
+
+ /* if the AVRCP is no longer listening, create the listening channel */
+ if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG)
+ bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+ }
+ }
+ else if((p_rcb->handle != BTA_AV_RC_HANDLE_NONE) && (p_rcb->status & BTA_AV_RC_CONN_MASK))
+ {
+ /* at least one channel is still connected */
+ conn = TRUE;
+ }
+ }
+
+ if(!conn)
+ {
+ /* no AVRC channels are connected, go back to INIT state */
+ bta_av_sm_execute(p_cb, BTA_AV_AVRC_NONE_EVT, NULL);
+ }
+
+ if (rc_close.rc_handle == BTA_AV_RC_HANDLE_NONE)
+ {
+ rc_close.rc_handle = p_msg->handle;
+ bdcpy(rc_close.peer_addr, p_msg->peer_addr);
+ }
+ (*p_cb->p_cback)(BTA_AV_RC_CLOSE_EVT, (tBTA_AV *) &rc_close);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rc_disc
+**
+** Description start AVRC SDP discovery.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_rc_disc(UINT8 disc)
+{
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ tAVRC_SDP_DB_PARAMS db_params;
+ UINT16 attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
+ ATTR_ID_BT_PROFILE_DESC_LIST,
+ ATTR_ID_SUPPORTED_FEATURES};
+ UINT8 hdi;
+ tBTA_AV_SCB *p_scb;
+ UINT8 *p_addr = NULL;
+ UINT8 rc_handle;
+
+ APPL_TRACE_DEBUG2("bta_av_rc_disc 0x%x, %d", disc, bta_av_cb.disc);
+ if ((bta_av_cb.disc != 0) || (disc == 0))
+ return;
+
+ if ((disc & BTA_AV_CHNL_MSK) == BTA_AV_CHNL_MSK)
+ {
+ /* this is the rc handle/index to tBTA_AV_RCB */
+ rc_handle = disc & (~BTA_AV_CHNL_MSK);
+ if (p_cb->rcb[rc_handle].lidx)
+ {
+ p_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx-1].addr;
+ }
+ }
+ else
+ {
+ hdi = (disc & BTA_AV_HNDL_MSK) - 1;
+ p_scb = p_cb->p_scb[hdi];
+
+ if (p_scb)
+ {
+ APPL_TRACE_DEBUG1("rc_handle %d", p_scb->rc_handle);
+ p_addr = p_scb->peer_addr;
+ }
+ }
+
+ if (p_addr)
+ {
+ /* allocate discovery database */
+ if (p_cb->p_disc_db == NULL)
+ {
+ p_cb->p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_AV_DISC_BUF_SIZE);
+ }
+
+ if (p_cb->p_disc_db)
+ {
+ /* set up parameters */
+ db_params.db_len = BTA_AV_DISC_BUF_SIZE;
+ db_params.num_attr = 3;
+ db_params.p_db = p_cb->p_disc_db;
+ db_params.p_attrs = attr_list;
+
+ /* searching for UUID_SERVCLASS_AV_REMOTE_CONTROL gets both TG and CT */
+ if (AVRC_FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, p_addr, &db_params,
+ bta_av_avrc_sdp_cback) == AVRC_SUCCESS)
+ {
+ p_cb->disc = disc;
+ APPL_TRACE_DEBUG1("disc %d", p_cb->disc);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_dereg_comp
+**
+** Description deregister complete. free the stream control block.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_dereg_comp(tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ tBTA_AV_SCB *p_scb;
+ tBTA_UTL_COD cod;
+ UINT8 mask;
+ BT_HDR *p_buf;
+
+ /* find the stream control block */
+ p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
+
+ if(p_scb)
+ {
+ APPL_TRACE_DEBUG2("deregistered %d(h%d)", p_scb->chnl, p_scb->hndl);
+ mask = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+ if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
+ {
+ p_cb->reg_audio &= ~mask;
+ if ((p_cb->conn_audio & mask) && bta_av_cb.audio_open_cnt)
+ {
+ /* this channel is still marked as open. decrease the count */
+ bta_av_cb.audio_open_cnt--;
+ }
+ p_cb->conn_audio &= ~mask;
+
+ if (p_scb->q_tag == BTA_AV_Q_TAG_STREAM)
+ {
+ /* make sure no buffers are in q_info.a2d */
+ while((p_buf = (BT_HDR*)GKI_dequeue (&p_scb->q_info.a2d)) != NULL)
+ GKI_freebuf(p_buf);
+ }
+
+ /* remove the A2DP SDP record, if no more audio stream is left */
+ if(!p_cb->reg_audio)
+ {
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+ bta_ar_dereg_avrc (UUID_SERVCLASS_AV_REMOTE_CONTROL, BTA_ID_AV);
+#endif
+ bta_av_del_sdp_rec(&p_cb->sdp_a2d_handle);
+ bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+ }
+ }
+ else
+ {
+ p_cb->reg_video &= ~mask;
+ /* make sure that this channel is not connected */
+ p_cb->conn_video &= ~mask;
+ /* remove the VDP SDP record, (only one video stream at most) */
+ bta_av_del_sdp_rec(&p_cb->sdp_vdp_handle);
+ bta_sys_remove_uuid(UUID_SERVCLASS_VIDEO_SOURCE);
+ }
+
+ /* make sure that the timer is not active */
+ bta_sys_stop_timer(&p_scb->timer);
+ utl_freebuf((void **)&p_cb->p_scb[p_scb->hdi]);
+ }
+
+ APPL_TRACE_DEBUG3("audio 0x%x, video: 0x%x, disable:%d",
+ p_cb->reg_audio, p_cb->reg_video, p_cb->disabling);
+ /* if no stream control block is active */
+ if((p_cb->reg_audio + p_cb->reg_video) == 0)
+ {
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+ /* deregister from AVDT */
+ bta_ar_dereg_avdt(BTA_ID_AV);
+
+ /* deregister from AVCT */
+ bta_ar_dereg_avrc (UUID_SERVCLASS_AV_REM_CTRL_TARGET, BTA_ID_AV);
+ bta_ar_dereg_avct(BTA_ID_AV);
+#endif
+
+ if(p_cb->disabling)
+ {
+ p_cb->disabling = FALSE;
+ bta_av_cb.features = 0;
+ }
+
+ /* Clear the Capturing service class bit */
+ cod.service = BTM_COD_SERVICE_CAPTURING;
+ utl_set_device_class(&cod, BTA_UTL_CLR_COD_SERVICE_CLASS);
+ }
+}
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/av/bta_av_api.c b/bta/av/bta_av_api.c
new file mode 100644
index 0000000..a58e4a6
--- /dev/null
+++ b/bta/av/bta_av_api.c
@@ -0,0 +1,581 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation of the API for the advanced audio/video (AV)
+ * subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ * phones.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_av_api.h"
+#include "bta_av_int.h"
+#include "gki.h"
+#include <string.h>
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_av_reg =
+{
+ bta_av_hdl_event,
+ BTA_AvDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_AvEnable
+**
+** Description Enable the advanced audio/video service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_AV_ENABLE_EVT. This function must
+** be called before other function in the AV API are
+** called.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvEnable(tBTA_SEC sec_mask, tBTA_AV_FEAT features, tBTA_AV_CBACK *p_cback)
+{
+ tBTA_AV_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_AV, &bta_av_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_AV_API_ENABLE *) GKI_getbuf(sizeof(tBTA_AV_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->features = features;
+ p_buf->sec_mask = sec_mask;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvDisable
+**
+** Description Disable the advanced audio/video service.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_AV);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AV_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvRegister
+**
+** Description Register the audio or video service to stack. When the
+** operation is complete the callback function will be
+** called with a BTA_AV_REGISTER_EVT. This function must
+** be called before AVDT stream is open.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id)
+{
+ tBTA_AV_API_REG *p_buf;
+
+
+ if ((p_buf = (tBTA_AV_API_REG *) GKI_getbuf(sizeof(tBTA_AV_API_REG))) != NULL)
+ {
+ p_buf->hdr.layer_specific = chnl;
+ p_buf->hdr.event = BTA_AV_API_REGISTER_EVT;
+ if(p_service_name)
+ {
+ BCM_STRNCPY_S(p_buf->p_service_name, sizeof(p_buf->p_service_name), p_service_name, BTA_SERVICE_NAME_LEN);
+ p_buf->p_service_name[BTA_SERVICE_NAME_LEN-1] = 0;
+ }
+ else
+ {
+ p_buf->p_service_name[0] = 0;
+ }
+ p_buf->app_id = app_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvDeregister
+**
+** Description Deregister the audio or video service
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvDeregister(tBTA_AV_HNDL hndl)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->layer_specific = hndl;
+ p_buf->event = BTA_AV_API_DEREGISTER_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvOpen
+**
+** Description Opens an advanced audio/video connection to a peer device.
+** When connection is open callback function is called
+** with a BTA_AV_OPEN_EVT.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle, BOOLEAN use_rc, tBTA_SEC sec_mask)
+{
+ tBTA_AV_API_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_OPEN *) GKI_getbuf(sizeof(tBTA_AV_API_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_OPEN_EVT;
+ p_buf->hdr.layer_specific = handle;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ p_buf->use_rc = use_rc;
+ p_buf->sec_mask = sec_mask;
+ p_buf->switch_res = BTA_AV_RS_NONE;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvClose
+**
+** Description Close the current streams.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvClose(tBTA_AV_HNDL handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AV_API_CLOSE_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvDisconnect
+**
+** Description Close the connection to the address.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvDisconnect(BD_ADDR bd_addr)
+{
+ tBTA_AV_API_DISCNT *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_DISCNT *) GKI_getbuf(sizeof(tBTA_AV_API_DISCNT))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_DISCONNECT_EVT;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvStart
+**
+** Description Start audio/video stream data transfer.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvStart(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_AV_API_START_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvStop
+**
+** Description Stop audio/video stream data transfer.
+** If suspend is TRUE, this function sends AVDT suspend signal
+** to the connected peer(s).
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvStop(BOOLEAN suspend)
+{
+ tBTA_AV_API_STOP *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_STOP *) GKI_getbuf(sizeof(tBTA_AV_API_STOP))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_STOP_EVT;
+ p_buf->flush = TRUE;
+ p_buf->suspend = suspend;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvReconfig
+**
+** Description Reconfigure the audio/video stream.
+** If suspend is TRUE, this function tries the suspend/reconfigure
+** procedure first.
+** If suspend is FALSE or when suspend/reconfigure fails,
+** this function closes and re-opens the AVDT connection.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvReconfig(tBTA_AV_HNDL hndl, BOOLEAN suspend, UINT8 sep_info_idx,
+ UINT8 *p_codec_info, UINT8 num_protect, UINT8 *p_protect_info)
+{
+ tBTA_AV_API_RCFG *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_RCFG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_RCFG) + num_protect))) != NULL)
+ {
+ p_buf->hdr.layer_specific = hndl;
+ p_buf->hdr.event = BTA_AV_API_RECONFIG_EVT;
+ p_buf->num_protect = num_protect;
+ p_buf->suspend = suspend;
+ p_buf->sep_info_idx = sep_info_idx;
+ p_buf->p_protect_info = (UINT8 *)(p_buf + 1);
+ memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE);
+ memcpy(p_buf->p_protect_info, p_protect_info, num_protect);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvProtectReq
+**
+** Description Send a content protection request. This function can only
+** be used if AV is enabled with feature BTA_AV_FEAT_PROTECT.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len)
+{
+ tBTA_AV_API_PROTECT_REQ *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_PROTECT_REQ *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_PROTECT_REQ) + len))) != NULL)
+ {
+ p_buf->hdr.layer_specific = hndl;
+ p_buf->hdr.event = BTA_AV_API_PROTECT_REQ_EVT;
+ p_buf->len = len;
+ if (p_data == NULL)
+ {
+ p_buf->p_data = NULL;
+ }
+ else
+ {
+ p_buf->p_data = (UINT8 *) (p_buf + 1);
+ memcpy(p_buf->p_data, p_data, len);
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvProtectRsp
+**
+** Description Send a content protection response. This function must
+** be called if a BTA_AV_PROTECT_REQ_EVT is received.
+** This function can only be used if AV is enabled with
+** feature BTA_AV_FEAT_PROTECT.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvProtectRsp(tBTA_AV_HNDL hndl, UINT8 error_code, UINT8 *p_data, UINT16 len)
+{
+ tBTA_AV_API_PROTECT_RSP *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_PROTECT_RSP *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_PROTECT_RSP) + len))) != NULL)
+ {
+ p_buf->hdr.layer_specific = hndl;
+ p_buf->hdr.event = BTA_AV_API_PROTECT_RSP_EVT;
+ p_buf->len = len;
+ p_buf->error_code = error_code;
+ if (p_data == NULL)
+ {
+ p_buf->p_data = NULL;
+ }
+ else
+ {
+ p_buf->p_data = (UINT8 *) (p_buf + 1);
+ memcpy(p_buf->p_data, p_data, len);
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvRemoteCmd
+**
+** Description Send a remote control command. This function can only
+** be used if AV is enabled with feature BTA_AV_FEAT_RCCT.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvRemoteCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_RC rc_id, tBTA_AV_STATE key_state)
+{
+ tBTA_AV_API_REMOTE_CMD *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_REMOTE_CMD *) GKI_getbuf(sizeof(tBTA_AV_API_REMOTE_CMD))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_REMOTE_CMD_EVT;
+ p_buf->hdr.layer_specific = rc_handle;
+ p_buf->msg.op_id = rc_id;
+ p_buf->msg.state = key_state;
+ p_buf->msg.p_pass_data = NULL;
+ p_buf->msg.pass_len = 0;
+ p_buf->label = label;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvVendorCmd
+**
+** Description Send a vendor dependent remote control command. This
+** function can only be used if AV is enabled with feature
+** BTA_AV_FEAT_VENDOR.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code, UINT8 *p_data, UINT16 len)
+{
+ tBTA_AV_API_VENDOR *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_VENDOR *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_VENDOR_CMD_EVT;
+ p_buf->hdr.layer_specific = rc_handle;
+ p_buf->msg.hdr.ctype = cmd_code;
+ p_buf->msg.hdr.subunit_type = AVRC_SUB_PANEL;
+ p_buf->msg.hdr.subunit_id = 0;
+ p_buf->msg.company_id = p_bta_av_cfg->company_id;
+ p_buf->label = label;
+ p_buf->msg.vendor_len = len;
+ if (p_data == NULL)
+ {
+ p_buf->msg.p_vendor_data = NULL;
+ }
+ else
+ {
+ p_buf->msg.p_vendor_data = (UINT8 *) (p_buf + 1);
+ memcpy(p_buf->msg.p_vendor_data, p_data, len);
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvVendorRsp
+**
+** Description Send a vendor dependent remote control response.
+** This function must be called if a BTA_AV_VENDOR_CMD_EVT
+** is received. This function can only be used if AV is
+** enabled with feature BTA_AV_FEAT_VENDOR.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvVendorRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code, UINT8 *p_data, UINT16 len, UINT32 company_id)
+{
+ tBTA_AV_API_VENDOR *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_VENDOR *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_VENDOR_RSP_EVT;
+ p_buf->hdr.layer_specific = rc_handle;
+ p_buf->msg.hdr.ctype = rsp_code;
+ p_buf->msg.hdr.subunit_type = AVRC_SUB_PANEL;
+ p_buf->msg.hdr.subunit_id = 0;
+ if(company_id)
+ p_buf->msg.company_id = company_id;
+ else
+ p_buf->msg.company_id = p_bta_av_cfg->company_id;
+ p_buf->label = label;
+ p_buf->msg.vendor_len = len;
+ if (p_data == NULL)
+ {
+ p_buf->msg.p_vendor_data = NULL;
+ }
+ else
+ {
+ p_buf->msg.p_vendor_data = (UINT8 *) (p_buf + 1);
+ memcpy(p_buf->msg.p_vendor_data, p_data, len);
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvOpenRc
+**
+** Description Open an AVRCP connection toward the device with the
+** specified handle
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvOpenRc(tBTA_AV_HNDL handle)
+{
+ tBTA_AV_API_OPEN_RC *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_OPEN_RC *) GKI_getbuf(sizeof(tBTA_AV_API_OPEN_RC))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_RC_OPEN_EVT;
+ p_buf->hdr.layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvCloseRc
+**
+** Description Close an AVRCP connection
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvCloseRc(UINT8 rc_handle)
+{
+ tBTA_AV_API_CLOSE_RC *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_CLOSE_RC *) GKI_getbuf(sizeof(tBTA_AV_API_CLOSE_RC))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_RC_CLOSE_EVT;
+ p_buf->hdr.layer_specific = rc_handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvMetaRsp
+**
+** Description Send a Metadata/Advanced Control response. The message contained
+** in p_pkt can be composed with AVRC utility functions.
+** This function can only be used if AV is enabled with feature
+** BTA_AV_FEAT_METADATA.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvMetaRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
+ BT_HDR *p_pkt)
+{
+ tBTA_AV_API_META_RSP *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_META_RSP *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_META_RSP)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_META_RSP_EVT;
+ p_buf->hdr.layer_specific = rc_handle;
+ p_buf->rsp_code = rsp_code;
+ p_buf->p_pkt = p_pkt;
+ p_buf->is_rsp = TRUE;
+ p_buf->label = label;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_AvMetaCmd
+**
+** Description Send a Metadata/Advanced Control command. The message contained
+** in p_pkt can be composed with AVRC utility functions.
+** This function can only be used if AV is enabled with feature
+** BTA_AV_FEAT_METADATA.
+** This message is sent only when the peer supports the TG role.
+*8 The only command makes sense right now is the absolute volume command.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p_pkt)
+{
+ tBTA_AV_API_META_RSP *p_buf;
+
+ if ((p_buf = (tBTA_AV_API_META_RSP *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_META_RSP)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_AV_API_META_RSP_EVT;
+ p_buf->hdr.layer_specific = rc_handle;
+ p_buf->p_pkt = p_pkt;
+ p_buf->rsp_code = cmd_code;
+ p_buf->is_rsp = FALSE;
+ p_buf->label = label;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c
new file mode 100644
index 0000000..793c772
--- /dev/null
+++ b/bta/av/bta_av_cfg.c
@@ -0,0 +1,231 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains compile-time configurable constants for advanced
+ * audio/video
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "gki.h"
+#include "bta_api.h"
+#include "bta_av_int.h"
+
+
+
+#ifndef BTA_AV_RC_PASS_RSP_CODE
+#define BTA_AV_RC_PASS_RSP_CODE BTA_AV_RSP_NOT_IMPL
+#endif
+
+
+const UINT32 bta_av_meta_caps_co_ids[] = {
+ AVRC_CO_METADATA,
+ AVRC_CO_BROADCOM
+};
+
+/* AVRCP cupported categories */
+#define BTA_AV_RC_SUPF_CT (AVRC_SUPF_CT_CAT2)
+
+
+/* Added to modify
+** 1. flush timeout
+** 2. Remove Group navigation support in SupportedFeatures
+** 3. GetCapabilities supported event_ids list
+** 4. GetCapabilities supported event_ids count
+*/
+#ifdef ANDROID_APP_INCLUDED
+/* Flushing partial avdtp packets can cause some headsets to disconnect the link
+ if receiving partial a2dp frames */
+const UINT16 bta_av_audio_flush_to[] = {
+ 0, /* 1 stream */
+ 0, /* 2 streams */
+ 0, /* 3 streams */
+ 0, /* 4 streams */
+ 0 /* 5 streams */
+}; /* AVDTP audio transport channel flush timeout */
+
+/* Note: Android doesnt support AVRC_SUPF_TG_GROUP_NAVI */
+#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1)
+
+
+/*
+ * If the number of event IDs is changed in this array, BTA_AV_ NUM_RC_EVT_IDS also needs to be changed.
+ */
+const UINT8 bta_av_meta_caps_evt_ids[] = {
+ AVRC_EVT_PLAY_STATUS_CHANGE,
+ AVRC_EVT_TRACK_CHANGE,
+ AVRC_EVT_PLAY_POS_CHANGED,
+ AVRC_EVT_APP_SETTING_CHANGE,
+};
+#ifndef BTA_AV_NUM_RC_EVT_IDS
+#define BTA_AV_NUM_RC_EVT_IDS (sizeof(bta_av_meta_caps_evt_ids) / sizeof(bta_av_meta_caps_evt_ids[0]))
+#endif /* BTA_AV_NUM_RC_EVT_IDS */
+
+
+#else /* !ANDROID_APP_INCLUDED */
+
+/* Note: if AVRC_SUPF_TG_GROUP_NAVI is set, bta_av_cfg.avrc_group should be TRUE */
+#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1)
+
+const UINT16 bta_av_audio_flush_to[] = {
+ 120, /* 1 stream */
+ 100, /* 2 streams */
+ 80, /* 3 streams */
+ 60, /* 4 streams */
+ 40 /* 5 streams */
+}; /* AVDTP audio transport channel flush timeout */
+
+
+/*
+ * If the number of event IDs is changed in this array, BTA_AV_ NUM_RC_EVT_IDS also needs to be changed.
+ */
+const UINT8 bta_av_meta_caps_evt_ids[] = {
+ AVRC_EVT_PLAY_STATUS_CHANGE,
+ AVRC_EVT_TRACK_CHANGE,
+ AVRC_EVT_TRACK_REACHED_END,
+ AVRC_EVT_TRACK_REACHED_START,
+ AVRC_EVT_PLAY_POS_CHANGED,
+ AVRC_EVT_BATTERY_STATUS_CHANGE,
+ AVRC_EVT_SYSTEM_STATUS_CHANGE,
+ AVRC_EVT_APP_SETTING_CHANGE,
+};
+
+#ifndef BTA_AV_NUM_RC_EVT_IDS
+#define BTA_AV_NUM_RC_EVT_IDS 8
+#endif
+
+#endif /* ANDROID_APP_INCLUDED */
+
+/* the MTU for the AVRCP browsing channel */
+#ifndef BTA_AV_MAX_RC_BR_MTU
+#define BTA_AV_MAX_RC_BR_MTU 1008
+#endif
+
+const tBTA_AV_CFG bta_av_cfg =
+{
+ AVRC_CO_BROADCOM, /* AVRCP Company ID */
+ 48, /* AVRCP MTU at L2CAP for control channel */
+ BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
+ BTA_AV_RC_SUPF_CT, /* AVRCP controller categories */
+ BTA_AV_RC_SUPF_TG, /* AVRCP target categories */
+ 672, /* AVDTP signaling channel MTU at L2CAP */
+ BTA_AV_MAX_A2DP_MTU, /* AVDTP audio transport channel MTU at L2CAP */
+ bta_av_audio_flush_to, /* AVDTP audio transport channel flush timeout */
+ 6, /* AVDTP audio channel max data queue size */
+ BTA_AV_MAX_VDP_MTU, /* AVDTP video transport channel MTU at L2CAP */
+ 600, /* AVDTP video transport channel flush timeout */
+ TRUE, /* TRUE, to accept AVRC 1.3 group nevigation command */
+ 2, /* company id count in p_meta_co_ids */
+ BTA_AV_NUM_RC_EVT_IDS, /* event id count in p_meta_evt_ids */
+ BTA_AV_RC_PASS_RSP_CODE,/* the default response code for pass through commands */
+ bta_av_meta_caps_co_ids,/* the metadata Get Capabilities response for company id */
+ bta_av_meta_caps_evt_ids,/* the the metadata Get Capabilities response for event id */
+};
+
+tBTA_AV_CFG *p_bta_av_cfg = (tBTA_AV_CFG *) &bta_av_cfg;
+
+const UINT16 bta_av_rc_id[] =
+{
+ 0x021F, /* bit mask: 0=SELECT, 1=UP, 2=DOWN, 3=LEFT,
+ 4=RIGHT, 5=RIGHT_UP, 6=RIGHT_DOWN, 7=LEFT_UP,
+ 8=LEFT_DOWN, 9=ROOT_MENU, 10=SETUP_MENU, 11=CONT_MENU,
+ 12=FAV_MENU, 13=EXIT */
+
+ 0, /* not used */
+
+ 0x0000, /* bit mask: 0=0, 1=1, 2=2, 3=3,
+ 4=4, 5=5, 6=6, 7=7,
+ 8=8, 9=9, 10=DOT, 11=ENTER,
+ 12=CLEAR */
+
+ 0x0003, /* bit mask: 0=CHAN_UP, 1=CHAN_DOWN, 2=PREV_CHAN, 3=SOUND_SEL,
+ 4=INPUT_SEL, 5=DISP_INFO, 6=HELP, 7=PAGE_UP,
+ 8=PAGE_DOWN */
+
+#if (BTA_AV_RC_PASS_RSP_CODE == BTA_AV_RSP_INTERIM)
+ /* btui_app provides an example of how to leave the decision of rejecting a command or not
+ * based on which media player is currently addressed (this is only applicable for AVRCP 1.4 or later)
+ * If the decision is per player for a particular rc_id, the related bit is clear (not set) */
+ 0x0070, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
+ 4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
+ 8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
+ 12=BACKWARD */
+#else
+#if (defined BTA_AVRCP_FF_RW_SUPPORT) && (BTA_AVRCP_FF_RW_SUPPORT == TRUE)
+ 0x1b70, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
+ 4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
+ 8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
+ 12=BACKWARD */
+#else
+ 0x1870, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
+ 4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
+ 8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
+ 12=BACKWARD */
+#endif
+#endif
+
+ 0x0000, /* bit mask: 0=ANGLE, 1=SUBPICT */
+
+ 0, /* not used */
+
+ 0x0000 /* bit mask: 0=not used, 1=F1, 2=F2, 3=F3,
+ 4=F4, 5=F5 */
+};
+
+#if (BTA_AV_RC_PASS_RSP_CODE == BTA_AV_RSP_INTERIM)
+const UINT16 bta_av_rc_id_ac[] =
+{
+ 0x0000, /* bit mask: 0=SELECT, 1=UP, 2=DOWN, 3=LEFT,
+ 4=RIGHT, 5=RIGHT_UP, 6=RIGHT_DOWN, 7=LEFT_UP,
+ 8=LEFT_DOWN, 9=ROOT_MENU, 10=SETUP_MENU, 11=CONT_MENU,
+ 12=FAV_MENU, 13=EXIT */
+
+ 0, /* not used */
+
+ 0x0000, /* bit mask: 0=0, 1=1, 2=2, 3=3,
+ 4=4, 5=5, 6=6, 7=7,
+ 8=8, 9=9, 10=DOT, 11=ENTER,
+ 12=CLEAR */
+
+ 0x0000, /* bit mask: 0=CHAN_UP, 1=CHAN_DOWN, 2=PREV_CHAN, 3=SOUND_SEL,
+ 4=INPUT_SEL, 5=DISP_INFO, 6=HELP, 7=PAGE_UP,
+ 8=PAGE_DOWN */
+
+ /* btui_app provides an example of how to leave the decision of rejecting a command or not
+ * based on which media player is currently addressed (this is only applicable for AVRCP 1.4 or later)
+ * If the decision is per player for a particular rc_id, the related bit is set */
+ 0x1800, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
+ 4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
+ 8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
+ 12=BACKWARD */
+
+ 0x0000, /* bit mask: 0=ANGLE, 1=SUBPICT */
+
+ 0, /* not used */
+
+ 0x0000 /* bit mask: 0=not used, 1=F1, 2=F2, 3=F3,
+ 4=F4, 5=F5 */
+};
+UINT16 *p_bta_av_rc_id_ac = (UINT16 *) bta_av_rc_id_ac;
+#else
+UINT16 *p_bta_av_rc_id_ac = NULL;
+#endif
+
+UINT16 *p_bta_av_rc_id = (UINT16 *) bta_av_rc_id;
diff --git a/bta/av/bta_av_ci.c b/bta/av/bta_av_ci.c
new file mode 100644
index 0000000..a1c2ac0
--- /dev/null
+++ b/bta/av/bta_av_ci.c
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation file for advanced audio/video call-in
+ * functions.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_av_int.h"
+#include "bta_av_ci.h"
+
+#include <string.h>
+
+/*******************************************************************************
+**
+** Function bta_av_ci_src_data_ready
+**
+** Description This function sends an event to the AV indicating that
+** the phone has audio stream data ready to send and AV
+** should call bta_av_co_audio_src_data_path() or
+** bta_av_co_video_src_data_path().
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_ci_src_data_ready(tBTA_AV_CHNL chnl)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->layer_specific = chnl;
+ p_buf->event = BTA_AV_CI_SRC_DATA_READY_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_ci_setconfig
+**
+** Description This function must be called in response to function
+** bta_av_co_audio_setconfig() or bta_av_co_video_setconfig.
+** Parameter err_code is set to an AVDTP status value;
+** AVDT_SUCCESS if the codec configuration is ok,
+** otherwise error.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code, UINT8 category,
+ UINT8 num_seid, UINT8 *p_seid, BOOLEAN recfg_needed)
+{
+ tBTA_AV_CI_SETCONFIG *p_buf;
+
+ if ((p_buf = (tBTA_AV_CI_SETCONFIG *) GKI_getbuf(sizeof(tBTA_AV_CI_SETCONFIG))) != NULL)
+ {
+ p_buf->hdr.layer_specific = hndl;
+ p_buf->hdr.event = (err_code == AVDT_SUCCESS) ?
+ BTA_AV_CI_SETCONFIG_OK_EVT : BTA_AV_CI_SETCONFIG_FAIL_EVT;
+ p_buf->err_code = err_code;
+ p_buf->category = category;
+ p_buf->recfg_needed = recfg_needed;
+ p_buf->num_seid = num_seid;
+ if(p_seid && num_seid)
+ {
+ p_buf->p_seid = (UINT8 *)(p_buf + 1);
+ memcpy(p_buf->p_seid, p_seid, num_seid);
+ }
+ else
+ {
+ p_buf->p_seid = NULL;
+ p_buf->num_seid = 0;
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h
new file mode 100644
index 0000000..05eb114
--- /dev/null
+++ b/bta/av/bta_av_int.h
@@ -0,0 +1,719 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private interface file for the BTA advanced audio/video.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_INT_H
+#define BTA_AV_INT_H
+
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_av_api.h"
+#include "avdt_api.h"
+#include "bta_av_co.h"
+
+#define BTA_AV_DEBUG TRUE
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+enum
+{
+ /* these events are handled by the AV main state machine */
+ BTA_AV_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_AV),
+ BTA_AV_API_REMOTE_CMD_EVT,
+ BTA_AV_API_VENDOR_CMD_EVT,
+ BTA_AV_API_VENDOR_RSP_EVT,
+ BTA_AV_API_META_RSP_EVT,
+ BTA_AV_API_RC_CLOSE_EVT,
+ BTA_AV_AVRC_OPEN_EVT,
+ BTA_AV_AVRC_MSG_EVT,
+ BTA_AV_AVRC_NONE_EVT,
+
+ /* these events are handled by the AV stream state machine */
+ BTA_AV_API_OPEN_EVT,
+ BTA_AV_API_CLOSE_EVT,
+ BTA_AV_AP_START_EVT, /* the following 2 events must be in the same order as the *API_*EVT */
+ BTA_AV_AP_STOP_EVT,
+ BTA_AV_API_RECONFIG_EVT,
+ BTA_AV_API_PROTECT_REQ_EVT,
+ BTA_AV_API_PROTECT_RSP_EVT,
+ BTA_AV_API_RC_OPEN_EVT,
+ BTA_AV_SRC_DATA_READY_EVT,
+ BTA_AV_CI_SETCONFIG_OK_EVT,
+ BTA_AV_CI_SETCONFIG_FAIL_EVT,
+ BTA_AV_SDP_DISC_OK_EVT,
+ BTA_AV_SDP_DISC_FAIL_EVT,
+ BTA_AV_STR_DISC_OK_EVT,
+ BTA_AV_STR_DISC_FAIL_EVT,
+ BTA_AV_STR_GETCAP_OK_EVT,
+ BTA_AV_STR_GETCAP_FAIL_EVT,
+ BTA_AV_STR_OPEN_OK_EVT,
+ BTA_AV_STR_OPEN_FAIL_EVT,
+ BTA_AV_STR_START_OK_EVT,
+ BTA_AV_STR_START_FAIL_EVT,
+ BTA_AV_STR_CLOSE_EVT,
+ BTA_AV_STR_CONFIG_IND_EVT,
+ BTA_AV_STR_SECURITY_IND_EVT,
+ BTA_AV_STR_SECURITY_CFM_EVT,
+ BTA_AV_STR_WRITE_CFM_EVT,
+ BTA_AV_STR_SUSPEND_CFM_EVT,
+ BTA_AV_STR_RECONFIG_CFM_EVT,
+ BTA_AV_AVRC_TIMER_EVT,
+ BTA_AV_AVDT_CONNECT_EVT,
+ BTA_AV_AVDT_DISCONNECT_EVT,
+ BTA_AV_ROLE_CHANGE_EVT,
+ BTA_AV_AVDT_DELAY_RPT_EVT,
+ BTA_AV_ACP_CONNECT_EVT,
+
+ /* these events are handled outside of the state machine */
+ BTA_AV_API_ENABLE_EVT,
+ BTA_AV_API_REGISTER_EVT,
+ BTA_AV_API_DEREGISTER_EVT,
+ BTA_AV_API_DISCONNECT_EVT,
+ BTA_AV_CI_SRC_DATA_READY_EVT,
+ BTA_AV_SIG_CHG_EVT,
+ BTA_AV_SIG_TIMER_EVT,
+ BTA_AV_SDP_AVRC_DISC_EVT,
+ BTA_AV_AVRC_CLOSE_EVT,
+ BTA_AV_CONN_CHG_EVT,
+ BTA_AV_DEREG_COMP_EVT,
+#if (AVDT_REPORTING == TRUE)
+ BTA_AV_AVDT_RPT_CONN_EVT,
+#endif
+ BTA_AV_API_START_EVT, /* the following 2 events must be in the same order as the *AP_*EVT */
+ BTA_AV_API_STOP_EVT
+};
+
+/* events for AV control block state machine */
+#define BTA_AV_FIRST_SM_EVT BTA_AV_API_DISABLE_EVT
+#define BTA_AV_LAST_SM_EVT BTA_AV_AVRC_NONE_EVT
+
+/* events for AV stream control block state machine */
+#define BTA_AV_FIRST_SSM_EVT BTA_AV_API_OPEN_EVT
+
+/* events that do not go through state machine */
+#define BTA_AV_FIRST_NSM_EVT BTA_AV_API_ENABLE_EVT
+#define BTA_AV_LAST_NSM_EVT BTA_AV_API_STOP_EVT
+
+/* API events passed to both SSMs (by bta_av_api_to_ssm) */
+#define BTA_AV_FIRST_A2S_API_EVT BTA_AV_API_START_EVT
+#define BTA_AV_FIRST_A2S_SSM_EVT BTA_AV_AP_START_EVT
+
+#define BTA_AV_LAST_EVT BTA_AV_API_STOP_EVT
+
+/* maximum number of SEPS in stream discovery results */
+#define BTA_AV_NUM_SEPS 32
+
+/* initialization value for AVRC handle */
+#define BTA_AV_RC_HANDLE_NONE 0xFF
+
+/* size of database for service discovery */
+#define BTA_AV_DISC_BUF_SIZE 1000
+
+/* offset of media type in codec info byte array */
+#define BTA_AV_MEDIA_TYPE_IDX 1
+
+/* maximum length of AVDTP security data */
+#define BTA_AV_SECURITY_MAX_LEN 400
+
+/* check number of buffers queued at L2CAP when this amount of buffers are queued to L2CAP */
+#define BTA_AV_QUEUE_DATA_CHK_NUM 5
+
+/* the number of ACL links with AVDT */
+#define BTA_AV_NUM_LINKS AVDT_NUM_LINKS
+
+#define BTA_AV_CO_ID_TO_BE_STREAM(p, u32) {*(p)++ = (UINT8)((u32) >> 16); *(p)++ = (UINT8)((u32) >> 8); *(p)++ = (UINT8)(u32); }
+#define BTA_AV_BE_STREAM_TO_CO_ID(u32, p) {u32 = (((UINT32)(*((p) + 2))) + (((UINT32)(*((p) + 1))) << 8) + (((UINT32)(*(p))) << 16)); (p) += 3;}
+
+/* these bits are defined for bta_av_cb.multi_av */
+#define BTA_AV_MULTI_AV_SUPPORTED 0x01
+#define BTA_AV_MULTI_AV_IN_USE 0x02
+
+
+/*****************************************************************************
+** Data types
+*****************************************************************************/
+
+/* function types for call-out functions */
+typedef BOOLEAN (*tBTA_AV_CO_INIT) (UINT8 *p_codec_type, UINT8 *p_codec_info,
+ UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 index);
+
+typedef void (*tBTA_AV_CO_DISC_RES) (tBTA_AV_HNDL hndl, UINT8 num_seps,
+ UINT8 num_snk, BD_ADDR addr);
+
+typedef UINT8 (*tBTA_AV_CO_GETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid,
+ UINT8 *p_num_protect, UINT8 *p_protect_info);
+typedef void (*tBTA_AV_CO_SETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
+ UINT8 num_protect, UINT8 *p_protect_info);
+typedef void (*tBTA_AV_CO_OPEN) (tBTA_AV_HNDL hndl,
+ tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
+ UINT16 mtu);
+typedef void (*tBTA_AV_CO_CLOSE) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT16 mtu);
+typedef void (*tBTA_AV_CO_START) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+typedef void (*tBTA_AV_CO_STOP) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+typedef void * (*tBTA_AV_CO_DATAPATH) (tBTA_AV_CODEC codec_type,
+ UINT32 *p_len, UINT32 *p_timestamp);
+typedef void (*tBTA_AV_CO_DELAY) (tBTA_AV_HNDL hndl, UINT16 delay);
+
+/* the call-out functions for one stream */
+typedef struct
+{
+ tBTA_AV_CO_INIT init;
+ tBTA_AV_CO_DISC_RES disc_res;
+ tBTA_AV_CO_GETCFG getcfg;
+ tBTA_AV_CO_SETCFG setcfg;
+ tBTA_AV_CO_OPEN open;
+ tBTA_AV_CO_CLOSE close;
+ tBTA_AV_CO_START start;
+ tBTA_AV_CO_STOP stop;
+ tBTA_AV_CO_DATAPATH data;
+ tBTA_AV_CO_DELAY delay;
+} tBTA_AV_CO_FUNCTS;
+
+/* data type for BTA_AV_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_AV_CBACK *p_cback;
+ tBTA_AV_FEAT features;
+ tBTA_SEC sec_mask;
+} tBTA_AV_API_ENABLE;
+
+/* data type for BTA_AV_API_REG_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char p_service_name[BTA_SERVICE_NAME_LEN+1];
+ UINT8 app_id;
+} tBTA_AV_API_REG;
+
+
+enum
+{
+ BTA_AV_RS_NONE, /* straight API call */
+ BTA_AV_RS_OK, /* the role switch result - successful */
+ BTA_AV_RS_FAIL, /* the role switch result - failed */
+ BTA_AV_RS_DONE /* the role switch is done - continue */
+};
+typedef UINT8 tBTA_AV_RS_RES;
+/* data type for BTA_AV_API_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ BOOLEAN use_rc;
+ tBTA_SEC sec_mask;
+ tBTA_AV_RS_RES switch_res;
+} tBTA_AV_API_OPEN;
+
+/* data type for BTA_AV_API_STOP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN suspend;
+ BOOLEAN flush;
+} tBTA_AV_API_STOP;
+
+/* data type for BTA_AV_API_DISCONNECT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_AV_API_DISCNT;
+
+/* data type for BTA_AV_API_PROTECT_REQ_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 *p_data;
+ UINT16 len;
+} tBTA_AV_API_PROTECT_REQ;
+
+/* data type for BTA_AV_API_PROTECT_RSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 *p_data;
+ UINT16 len;
+ UINT8 error_code;
+} tBTA_AV_API_PROTECT_RSP;
+
+/* data type for BTA_AV_API_REMOTE_CMD_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tAVRC_MSG_PASS msg;
+ UINT8 label;
+} tBTA_AV_API_REMOTE_CMD;
+
+/* data type for BTA_AV_API_VENDOR_CMD_EVT and RSP */
+typedef struct
+{
+ BT_HDR hdr;
+ tAVRC_MSG_VENDOR msg;
+ UINT8 label;
+} tBTA_AV_API_VENDOR;
+
+/* data type for BTA_AV_API_RC_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+} tBTA_AV_API_OPEN_RC;
+
+/* data type for BTA_AV_API_RC_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+} tBTA_AV_API_CLOSE_RC;
+
+/* data type for BTA_AV_API_META_RSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN is_rsp;
+ UINT8 label;
+ tBTA_AV_CODE rsp_code;
+ BT_HDR *p_pkt;
+} tBTA_AV_API_META_RSP;
+
+
+/* data type for BTA_AV_API_RECONFIG_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 codec_info[AVDT_CODEC_SIZE]; /* codec configuration */
+ UINT8 *p_protect_info;
+ UINT8 num_protect;
+ BOOLEAN suspend;
+ UINT8 sep_info_idx;
+} tBTA_AV_API_RCFG;
+
+/* data type for BTA_AV_CI_SETCONFIG_OK_EVT and BTA_AV_CI_SETCONFIG_FAIL_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_AV_HNDL hndl;
+ UINT8 err_code;
+ UINT8 category;
+ UINT8 num_seid;
+ UINT8 *p_seid;
+ BOOLEAN recfg_needed;
+} tBTA_AV_CI_SETCONFIG;
+
+/* data type for all stream events from AVDTP */
+typedef struct {
+ BT_HDR hdr;
+ tAVDT_CFG cfg; /* configuration/capabilities parameters */
+ tAVDT_CTRL msg; /* AVDTP callback message parameters */
+ BD_ADDR bd_addr; /* bd address */
+ UINT8 handle;
+ UINT8 avdt_event;
+ BOOLEAN initiator; /* TRUE, if local device initiates the SUSPEND */
+} tBTA_AV_STR_MSG;
+
+/* data type for BTA_AV_AVRC_MSG_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tAVRC_MSG msg;
+ UINT8 handle;
+ UINT8 label;
+ UINT8 opcode;
+} tBTA_AV_RC_MSG;
+
+/* data type for BTA_AV_AVRC_OPEN_EVT, BTA_AV_AVRC_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR peer_addr;
+ UINT8 handle;
+} tBTA_AV_RC_CONN_CHG;
+
+/* data type for BTA_AV_CONN_CHG_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR peer_addr;
+ BOOLEAN is_up;
+} tBTA_AV_CONN_CHG;
+
+/* data type for BTA_AV_ROLE_CHANGE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 new_role;
+ UINT8 hci_status;
+} tBTA_AV_ROLE_RES;
+
+/* data type for BTA_AV_SDP_DISC_OK_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 avdt_version; /* AVDTP protocol version */
+} tBTA_AV_SDP_RES;
+
+/* type for SEP control block */
+typedef struct
+{
+ UINT8 av_handle; /* AVDTP handle */
+ tBTA_AV_CODEC codec_type; /* codec type */
+} tBTA_AV_SEP;
+
+
+/* initiator/acceptor role for adaption */
+#define BTA_AV_ROLE_AD_INT 0x00 /* initiator */
+#define BTA_AV_ROLE_AD_ACP 0x01 /* acceptor */
+
+/* initiator/acceptor signaling roles */
+#define BTA_AV_ROLE_START_ACP 0x00
+#define BTA_AV_ROLE_START_INT 0x10 /* do not change this value */
+
+#define BTA_AV_ROLE_SUSPEND 0x20 /* suspending on start */
+#define BTA_AV_ROLE_SUSPEND_OPT 0x40 /* Suspend on Start option is set */
+
+/* union of all event datatypes */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_AV_API_ENABLE api_enable;
+ tBTA_AV_API_REG api_reg;
+ tBTA_AV_API_OPEN api_open;
+ tBTA_AV_API_STOP api_stop;
+ tBTA_AV_API_DISCNT api_discnt;
+ tBTA_AV_API_PROTECT_REQ api_protect_req;
+ tBTA_AV_API_PROTECT_RSP api_protect_rsp;
+ tBTA_AV_API_REMOTE_CMD api_remote_cmd;
+ tBTA_AV_API_VENDOR api_vendor;
+ tBTA_AV_API_RCFG api_reconfig;
+ tBTA_AV_CI_SETCONFIG ci_setconfig;
+ tBTA_AV_STR_MSG str_msg;
+ tBTA_AV_RC_MSG rc_msg;
+ tBTA_AV_RC_CONN_CHG rc_conn_chg;
+ tBTA_AV_CONN_CHG conn_chg;
+ tBTA_AV_ROLE_RES role_res;
+ tBTA_AV_SDP_RES sdp_res;
+ tBTA_AV_API_META_RSP api_meta_rsp;
+} tBTA_AV_DATA;
+
+typedef void (tBTA_AV_VDP_DATA_ACT)(void *p_scb);
+
+typedef struct
+{
+ tBTA_AV_VDP_DATA_ACT *p_act;
+ UINT8 *p_frame;
+ UINT16 buf_size;
+ UINT32 len;
+ UINT32 offset;
+ UINT32 timestamp;
+} tBTA_AV_VF_INFO;
+
+typedef union
+{
+ BUFFER_Q a2d; /* used for audio channels only */
+ tBTA_AV_VF_INFO vdp; /* used for video channels only */
+ tBTA_AV_API_OPEN open; /* used only before open and role switch
+ is needed on another AV channel */
+} tBTA_AV_Q_INFO;
+
+#define BTA_AV_Q_TAG_OPEN 0x01 /* after API_OPEN, before STR_OPENED */
+#define BTA_AV_Q_TAG_START 0x02 /* before start sending media packets */
+#define BTA_AV_Q_TAG_STREAM 0x03 /* during streaming */
+
+#define BTA_AV_WAIT_ACP_CAPS_ON 0x01 /* retriving the peer capabilities */
+#define BTA_AV_WAIT_ACP_CAPS_STARTED 0x02 /* started while retriving peer capabilities */
+#define BTA_AV_WAIT_ROLE_SW_RES_OPEN 0x04 /* waiting for role switch result after API_OPEN, before STR_OPENED */
+#define BTA_AV_WAIT_ROLE_SW_RES_START 0x08 /* waiting for role switch result before streaming */
+#define BTA_AV_WAIT_ROLE_SW_STARTED 0x10 /* started while waiting for role switch result */
+#define BTA_AV_WAIT_ROLE_SW_RETRY 0x20 /* set when retry on timeout */
+#define BTA_AV_WAIT_CHECK_RC 0x40 /* set when the timer is used by role switch */
+#define BTA_AV_WAIT_ROLE_SW_FAILED 0x80 /* role switch failed */
+
+#define BTA_AV_WAIT_ROLE_SW_BITS (BTA_AV_WAIT_ROLE_SW_RES_OPEN|BTA_AV_WAIT_ROLE_SW_RES_START|BTA_AV_WAIT_ROLE_SW_STARTED|BTA_AV_WAIT_ROLE_SW_RETRY)
+
+/* Bitmap for collision, coll_mask */
+#define BTA_AV_COLL_INC_TMR 0x01 /* Timer is running for incoming L2C connection */
+#define BTA_AV_COLL_API_CALLED 0x02 /* API open was called while incoming timer is running */
+
+/* type for AV stream control block */
+typedef struct
+{
+ const tBTA_AV_ACT *p_act_tbl; /* the action table for stream state machine */
+ const tBTA_AV_CO_FUNCTS *p_cos; /* the associated callout functions */
+ tSDP_DISCOVERY_DB *p_disc_db; /* pointer to discovery database */
+ tBTA_AV_SEP seps[BTA_AV_MAX_SEPS];
+ tAVDT_CFG *p_cap; /* buffer used for get capabilities */
+ tBTA_AV_Q_INFO q_info;
+ tAVDT_SEP_INFO sep_info[BTA_AV_NUM_SEPS]; /* stream discovery results */
+ tAVDT_CFG cfg; /* local SEP configuration */
+ TIMER_LIST_ENT timer; /* delay timer for AVRC CT */
+ BD_ADDR peer_addr; /* peer BD address */
+ UINT16 l2c_cid; /* L2CAP channel ID */
+ UINT16 stream_mtu; /* MTU of stream */
+ UINT16 avdt_version; /* the avdt version of peer device */
+ tBTA_SEC sec_mask; /* security mask */
+ tBTA_AV_CODEC codec_type; /* codec type */
+ UINT8 media_type; /* Media type */
+ BOOLEAN cong; /* TRUE if AVDTP congested */
+ tBTA_AV_STATUS open_status; /* open failure status */
+ tBTA_AV_CHNL chnl; /* the channel: audio/video */
+ tBTA_AV_HNDL hndl; /* the handle: ((hdi + 1)|chnl) */
+ UINT16 cur_psc_mask; /* Protocol service capabilities mask for current connection */
+ UINT8 avdt_handle; /* AVDTP handle */
+ UINT8 hdi; /* the index to SCB[] */
+ UINT8 num_seps; /* number of seps returned by stream discovery */
+ UINT8 num_disc_snks; /* number of discovered snks */
+ UINT8 sep_info_idx; /* current index into sep_info */
+ UINT8 sep_idx; /* current index into local seps[] */
+ UINT8 rcfg_idx; /* reconfig requested index into sep_info */
+ UINT8 state; /* state machine state */
+ UINT8 avdt_label; /* AVDTP label */
+ UINT8 app_id; /* application id */
+ UINT8 num_recfg; /* number of reconfigure sent */
+ UINT8 role;
+ UINT8 l2c_bufs; /* the number of buffers queued to L2CAP */
+ UINT8 rc_handle; /* connected AVRCP handle */
+ BOOLEAN use_rc; /* TRUE if AVRCP is allowed */
+ BOOLEAN started; /* TRUE if stream started */
+ UINT8 co_started; /* non-zero, if stream started from call-out perspective */
+ BOOLEAN recfg_sup; /* TRUE if the first attempt to reconfigure the stream was successfull, else False if command fails */
+ BOOLEAN suspend_sup; /* TRUE if Suspend stream is supported, else FALSE if suspend command fails */
+ BOOLEAN deregistring; /* TRUE if deregistering */
+ BOOLEAN sco_suspend; /* TRUE if SUSPEND is issued automatically for SCO */
+ UINT8 coll_mask; /* Mask to check incoming and outgoing collision */
+ tBTA_AV_API_OPEN open_api; /* Saved OPEN api message */
+ UINT8 wait; /* set 0x1, when getting Caps as ACP, set 0x2, when started */
+ UINT8 q_tag; /* identify the associated q_info union member */
+} tBTA_AV_SCB;
+
+#define BTA_AV_RC_ROLE_MASK 0x10
+#define BTA_AV_RC_ROLE_INT 0x00
+#define BTA_AV_RC_ROLE_ACP 0x10
+
+#define BTA_AV_RC_CONN_MASK 0x20
+
+/* type for AV RCP control block */
+/* index to this control block is the rc handle */
+typedef struct
+{
+ UINT8 status;
+ UINT8 handle;
+ UINT8 shdl; /* stream handle (hdi + 1) */
+ UINT8 lidx; /* (index+1) to LCB */
+ tBTA_AV_FEAT peer_features; /* peer features mask */
+} tBTA_AV_RCB;
+#define BTA_AV_NUM_RCB (BTA_AV_NUM_STRS + 2)
+
+enum
+{
+ BTA_AV_LCB_FREE,
+ BTA_AV_LCB_FIND
+};
+
+/* type for AV ACL Link control block */
+typedef struct
+{
+ BD_ADDR addr; /* peer BD address */
+ UINT8 conn_msk; /* handle mask of connected stream handle */
+ UINT8 lidx; /* index + 1 */
+} tBTA_AV_LCB;
+
+/* type for stream state machine action functions */
+typedef void (*tBTA_AV_SACT)(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+
+
+/* type for AV control block */
+typedef struct
+{
+ tBTA_AV_SCB *p_scb[BTA_AV_NUM_STRS]; /* stream control block */
+ tSDP_DISCOVERY_DB *p_disc_db; /* pointer to discovery database */
+ tBTA_AV_CBACK *p_cback; /* application callback function */
+ tBTA_AV_RCB rcb[BTA_AV_NUM_RCB]; /* RCB control block */
+ tBTA_AV_LCB lcb[BTA_AV_NUM_LINKS+1]; /* link control block */
+ TIMER_LIST_ENT sig_tmr; /* link timer */
+ TIMER_LIST_ENT acp_sig_tmr; /* timer to monitor signalling when accepting */
+ UINT32 sdp_a2d_handle; /* SDP record handle for audio src */
+ UINT32 sdp_vdp_handle; /* SDP record handle for video src */
+ tBTA_AV_FEAT features; /* features mask */
+ tBTA_SEC sec_mask; /* security mask */
+ tBTA_AV_HNDL handle; /* the handle for SDP activity */
+ BOOLEAN disabling; /* TRUE if api disabled called */
+ UINT8 disc; /* (hdi+1) or (rc_handle|BTA_AV_CHNL_MSK) if p_disc_db is in use */
+ UINT8 state; /* state machine state */
+ UINT8 conn_rc; /* handle mask of connected RCP channels */
+ UINT8 conn_audio; /* handle mask of connected audio channels */
+ UINT8 conn_video; /* handle mask of connected video channels */
+ UINT8 conn_lcb; /* index mask of used LCBs */
+ UINT8 audio_open_cnt; /* number of connected audio channels */
+ UINT8 reg_audio; /* handle mask of registered audio channels */
+ UINT8 reg_video; /* handle mask of registered video channels */
+ UINT8 rc_acp_handle;
+ UINT8 rc_acp_idx; /* (index + 1) to RCB */
+ UINT8 rs_idx; /* (index + 1) to SCB for the one waiting for RS on open */
+ BOOLEAN sco_occupied; /* TRUE if SCO is being used or call is in progress */
+ UINT8 audio_streams; /* handle mask of streaming audio channels */
+ UINT8 video_streams; /* handle mask of streaming video channels */
+} tBTA_AV_CB;
+
+
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* control block declaration */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_AV_CB bta_av_cb;
+#else
+extern tBTA_AV_CB *bta_av_cb_ptr;
+#define bta_av_cb (*bta_av_cb_ptr)
+#endif
+
+/* config struct */
+extern tBTA_AV_CFG *p_bta_av_cfg;
+
+/* rc id config struct */
+extern UINT16 *p_bta_av_rc_id;
+extern UINT16 *p_bta_av_rc_id_ac;
+
+extern const tBTA_AV_SACT bta_av_a2d_action[];
+extern const tBTA_AV_CO_FUNCTS bta_av_a2d_cos;
+extern const tBTA_AV_SACT bta_av_vdp_action[];
+extern tAVDT_CTRL_CBACK * const bta_av_dt_cback[];
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+/* utility functions */
+extern tBTA_AV_SCB *bta_av_hndl_to_scb(UINT16 handle);
+extern BOOLEAN bta_av_chk_start(tBTA_AV_SCB *p_scb);
+extern void bta_av_restore_switch (void);
+extern UINT16 bta_av_chk_mtu(tBTA_AV_SCB *p_scb, UINT16 mtu);
+extern void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+extern UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx);
+extern void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data, int index);
+extern void bta_av_stream_chg(tBTA_AV_SCB *p_scb, BOOLEAN started);
+extern BOOLEAN bta_av_is_scb_opening (tBTA_AV_SCB *p_scb);
+extern BOOLEAN bta_av_is_scb_incoming (tBTA_AV_SCB *p_scb);
+extern void bta_av_set_scb_sst_init (tBTA_AV_SCB *p_scb);
+extern BOOLEAN bta_av_is_scb_init (tBTA_AV_SCB *p_scb);
+extern void bta_av_set_scb_sst_incoming (tBTA_AV_SCB *p_scb);
+extern tBTA_AV_LCB * bta_av_find_lcb(BD_ADDR addr, UINT8 op);
+
+
+/* main functions */
+extern void bta_av_api_deregister(tBTA_AV_DATA *p_data);
+extern void bta_av_dup_audio_buf(tBTA_AV_SCB *p_scb, BT_HDR *p_buf);
+extern void bta_av_sm_execute(tBTA_AV_CB *p_cb, UINT16 event, tBTA_AV_DATA *p_data);
+extern void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data);
+extern BOOLEAN bta_av_hdl_event(BT_HDR *p_msg);
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+extern char *bta_av_evt_code(UINT16 evt_code);
+#endif
+extern BOOLEAN bta_av_switch_if_needed(tBTA_AV_SCB *p_scb);
+extern BOOLEAN bta_av_link_role_ok(tBTA_AV_SCB *p_scb, UINT8 bits);
+extern BOOLEAN bta_av_is_rcfg_sst(tBTA_AV_SCB *p_scb);
+
+/* nsm action functions */
+extern void bta_av_api_disconnect(tBTA_AV_DATA *p_data);
+extern void bta_av_sig_chg(tBTA_AV_DATA *p_data);
+extern void bta_av_sig_timer(tBTA_AV_DATA *p_data);
+extern void bta_av_rc_disc_done(tBTA_AV_DATA *p_data);
+extern void bta_av_rc_closed(tBTA_AV_DATA *p_data);
+extern void bta_av_rc_disc(UINT8 disc);
+extern void bta_av_conn_chg(tBTA_AV_DATA *p_data);
+extern void bta_av_dereg_comp(tBTA_AV_DATA *p_data);
+
+/* sm action functions */
+extern void bta_av_disable (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_opened (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_remote_cmd (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_vendor_cmd (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_vendor_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_close (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_meta_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_free_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_free_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+
+extern tBTA_AV_RCB * bta_av_get_rcb_by_shdl(UINT8 shdl);
+extern void bta_av_del_rc(tBTA_AV_RCB *p_rcb);
+
+/* ssm action functions */
+extern void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_cleanup (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_free_sdb (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_disconnect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_st_rc_timer(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_do_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_connect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_sdp_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_disc_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_disc_res_as_acp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_setconfig_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_discover_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_conn_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_do_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_reconfig (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_data_path (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_start_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_clr_cong (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_str_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_connect (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_discntd (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_open (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_open_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_chk_2nd_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_save_caps (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rej_conn (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rej_conn (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_set_use_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_cco_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_switch_role (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_delay_co (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+
+/* ssm action functions - vdp specific */
+extern void bta_av_do_disc_vdp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_vdp_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_reg_vdp (tAVDT_CS *p_cs, char *p_service_name, void *p_data);
+
+#endif /* BTA_AV_INT_H */
diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c
new file mode 100644
index 0000000..085362d
--- /dev/null
+++ b/bta/av/bta_av_main.c
@@ -0,0 +1,1323 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the main implementation file for the BTA advanced audio/video.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_av_int.h"
+#include "utl.h"
+#include "bd.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+#include "bta_av_co.h"
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* AVDTP protocol timeout values */
+#ifndef BTA_AV_RET_TOUT
+#define BTA_AV_RET_TOUT 4
+#endif
+
+#ifndef BTA_AV_SIG_TOUT
+#define BTA_AV_SIG_TOUT 4
+#endif
+
+#ifndef BTA_AV_IDLE_TOUT
+#define BTA_AV_IDLE_TOUT 10
+#endif
+
+/* the delay time in milliseconds to retry role switch */
+#ifndef BTA_AV_RS_TIME_VAL
+#define BTA_AV_RS_TIME_VAL 1000
+#endif
+
+/* state machine states */
+enum
+{
+ BTA_AV_INIT_ST,
+ BTA_AV_OPEN_ST
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_AV_DISABLE,
+ BTA_AV_RC_OPENED,
+ BTA_AV_RC_REMOTE_CMD,
+ BTA_AV_RC_VENDOR_CMD,
+ BTA_AV_RC_VENDOR_RSP,
+ BTA_AV_RC_FREE_RSP,
+ BTA_AV_RC_FREE_MSG,
+ BTA_AV_RC_META_RSP,
+ BTA_AV_RC_MSG,
+ BTA_AV_RC_CLOSE,
+ BTA_AV_NUM_ACTIONS
+};
+
+#define BTA_AV_IGNORE BTA_AV_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tBTA_AV_ACTION)(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+
+/* action functions */
+const tBTA_AV_ACTION bta_av_action[] =
+{
+ bta_av_disable,
+ bta_av_rc_opened,
+ bta_av_rc_remote_cmd,
+ bta_av_rc_vendor_cmd,
+ bta_av_rc_vendor_rsp,
+ bta_av_rc_free_rsp,
+ bta_av_rc_free_msg,
+ bta_av_rc_meta_rsp,
+ bta_av_rc_msg,
+ bta_av_rc_close,
+ NULL
+};
+
+/* state table information */
+#define BTA_AV_ACTION_COL 0 /* position of actions */
+#define BTA_AV_NEXT_STATE 1 /* position of next state */
+#define BTA_AV_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for init state */
+static const UINT8 bta_av_st_init[][BTA_AV_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* API_DISABLE_EVT */ {BTA_AV_DISABLE, BTA_AV_INIT_ST },
+/* API_REMOTE_CMD_EVT */ {BTA_AV_IGNORE, BTA_AV_INIT_ST },
+/* API_VENDOR_CMD_EVT */ {BTA_AV_IGNORE, BTA_AV_INIT_ST },
+/* API_VENDOR_RSP_EVT */ {BTA_AV_IGNORE, BTA_AV_INIT_ST },
+/* API_META_RSP_EVT */ {BTA_AV_RC_FREE_RSP, BTA_AV_INIT_ST },
+/* API_RC_CLOSE_EVT */ {BTA_AV_IGNORE, BTA_AV_INIT_ST },
+/* AVRC_OPEN_EVT */ {BTA_AV_RC_OPENED, BTA_AV_OPEN_ST },
+/* AVRC_MSG_EVT */ {BTA_AV_RC_FREE_MSG, BTA_AV_INIT_ST },
+/* AVRC_NONE_EVT */ {BTA_AV_IGNORE, BTA_AV_INIT_ST },
+};
+
+/* state table for open state */
+static const UINT8 bta_av_st_open[][BTA_AV_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* API_DISABLE_EVT */ {BTA_AV_DISABLE, BTA_AV_INIT_ST },
+/* API_REMOTE_CMD_EVT */ {BTA_AV_RC_REMOTE_CMD, BTA_AV_OPEN_ST },
+/* API_VENDOR_CMD_EVT */ {BTA_AV_RC_VENDOR_CMD, BTA_AV_OPEN_ST },
+/* API_VENDOR_RSP_EVT */ {BTA_AV_RC_VENDOR_RSP, BTA_AV_OPEN_ST },
+/* API_META_RSP_EVT */ {BTA_AV_RC_META_RSP, BTA_AV_OPEN_ST },
+/* API_RC_CLOSE_EVT */ {BTA_AV_RC_CLOSE, BTA_AV_OPEN_ST },
+/* AVRC_OPEN_EVT */ {BTA_AV_RC_OPENED, BTA_AV_OPEN_ST },
+/* AVRC_MSG_EVT */ {BTA_AV_RC_MSG, BTA_AV_OPEN_ST },
+/* AVRC_NONE_EVT */ {BTA_AV_IGNORE, BTA_AV_INIT_ST },
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_AV_ST_TBL)[BTA_AV_NUM_COLS];
+
+/* state table */
+static const tBTA_AV_ST_TBL bta_av_st_tbl[] =
+{
+ bta_av_st_init,
+ bta_av_st_open
+};
+
+typedef void (*tBTA_AV_NSM_ACT)(tBTA_AV_DATA *p_data);
+static void bta_av_api_enable(tBTA_AV_DATA *p_data);
+static void bta_av_api_register(tBTA_AV_DATA *p_data);
+static void bta_av_ci_data(tBTA_AV_DATA *p_data);
+#if (AVDT_REPORTING == TRUE)
+static void bta_av_rpc_conn(tBTA_AV_DATA *p_data);
+#endif
+static void bta_av_api_to_ssm(tBTA_AV_DATA *p_data);
+
+static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8
+ app_id, BD_ADDR peer_addr);
+static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+
+/* action functions */
+const tBTA_AV_NSM_ACT bta_av_nsm_act[] =
+{
+ bta_av_api_enable, /* BTA_AV_API_ENABLE_EVT */
+ bta_av_api_register, /* BTA_AV_API_REGISTER_EVT */
+ bta_av_api_deregister, /* BTA_AV_API_DEREGISTER_EVT */
+ bta_av_api_disconnect, /* BTA_AV_API_DISCONNECT_EVT */
+ bta_av_ci_data, /* BTA_AV_CI_SRC_DATA_READY_EVT */
+ bta_av_sig_chg, /* BTA_AV_SIG_CHG_EVT */
+ bta_av_sig_timer, /* BTA_AV_SIG_TIMER_EVT */
+ bta_av_rc_disc_done, /* BTA_AV_SDP_AVRC_DISC_EVT */
+ bta_av_rc_closed, /* BTA_AV_AVRC_CLOSE_EVT */
+ bta_av_conn_chg, /* BTA_AV_CONN_CHG_EVT */
+ bta_av_dereg_comp, /* BTA_AV_DEREG_COMP_EVT */
+#if (AVDT_REPORTING == TRUE)
+ bta_av_rpc_conn, /* BTA_AV_AVDT_RPT_CONN_EVT */
+#endif
+ bta_av_api_to_ssm, /* BTA_AV_API_START_EVT */
+ bta_av_api_to_ssm, /* BTA_AV_API_STOP_EVT */
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* AV control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_AV_CB bta_av_cb;
+#endif
+
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+static char *bta_av_st_code(UINT8 state);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_av_timer_cback
+**
+** Description forward the event to stream state machine
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_timer_cback(void *p_tle)
+{
+ BT_HDR *p_buf;
+ TIMER_LIST_ENT *p = (TIMER_LIST_ENT *)p_tle;
+ int xx;
+ tBTA_AV_SCB *p_scb = NULL;
+
+ /* find the SCB that has the timer */
+ for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+ {
+ if(bta_av_cb.p_scb[xx] && &(bta_av_cb.p_scb[xx]->timer)== p)
+ {
+ p_scb = bta_av_cb.p_scb[xx];
+ break;
+ }
+ }
+
+ if (p_scb && (p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ /* send the event through the audio state machine.
+ * only when the audio SM is open, the main SM opens the RC connection as INT */
+ p_buf->event = p->event;
+ p_buf->layer_specific = p_scb->hndl;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_api_enable
+**
+** Description Handle an API enable event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_api_enable(tBTA_AV_DATA *p_data)
+{
+ int i;
+ tBTA_AV_ENABLE enable;
+
+ /* initialize control block */
+ memset(&bta_av_cb, 0, sizeof(tBTA_AV_CB));
+
+ for(i=0; i<BTA_AV_NUM_RCB; i++)
+ bta_av_cb.rcb[i].handle = BTA_AV_RC_HANDLE_NONE;
+
+ bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE;
+
+ /* store parameters */
+ bta_av_cb.p_cback = p_data->api_enable.p_cback;
+ bta_av_cb.features = p_data->api_enable.features;
+ bta_av_cb.sec_mask = p_data->api_enable.sec_mask;
+
+ enable.features = bta_av_cb.features;
+
+ /* Register for SCO change event */
+ if (!(bta_av_cb.features & BTA_AV_FEAT_NO_SCO_SSPD))
+ {
+ bta_sys_sco_register(bta_av_sco_chg_cback);
+ }
+
+ /* call callback with enable event */
+ (*bta_av_cb.p_cback)(BTA_AV_ENABLE_EVT, (tBTA_AV *)&enable);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_addr_to_scb
+**
+** Description find the stream control block by the peer addr
+**
+** Returns void
+**
+*******************************************************************************/
+static tBTA_AV_SCB * bta_av_addr_to_scb(BD_ADDR bd_addr)
+{
+ tBTA_AV_SCB * p_scb = NULL;
+ int xx;
+
+ for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+ {
+ if(bta_av_cb.p_scb[xx])
+ {
+ if(!bdcmp(bd_addr, bta_av_cb.p_scb[xx]->peer_addr))
+ {
+ p_scb = bta_av_cb.p_scb[xx];
+ break;
+ }
+ }
+ }
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_hndl_to_scb
+**
+** Description find the stream control block by the handle
+**
+** Returns void
+**
+*******************************************************************************/
+tBTA_AV_SCB * bta_av_hndl_to_scb(UINT16 handle)
+{
+ tBTA_AV_HNDL hndl = (tBTA_AV_HNDL)handle;
+ tBTA_AV_SCB * p_scb = NULL;
+ UINT8 idx = (hndl & BTA_AV_HNDL_MSK);
+
+ if(idx && (idx <= BTA_AV_NUM_STRS) )
+ {
+ p_scb = bta_av_cb.p_scb[idx-1];
+ }
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_alloc_scb
+**
+** Description allocate stream control block,
+** register the service to stack
+** create SDP record
+**
+** Returns void
+**
+*******************************************************************************/
+static tBTA_AV_SCB * bta_av_alloc_scb(tBTA_AV_CHNL chnl)
+{
+ tBTA_AV_SCB *p_ret = NULL;
+ int xx;
+ tBTA_AV_STATUS sts = BTA_AV_SUCCESS;
+
+ if(chnl == BTA_AV_CHNL_VIDEO)
+ {
+ if(p_bta_av_cfg->p_act_tbl == NULL || p_bta_av_cfg->p_reg == NULL)
+ {
+ APPL_TRACE_ERROR0("Video streaming not supported");
+ sts = BTA_AV_FAIL;
+ }
+ else
+ {
+ /* allow only one Video channel */
+ if(bta_av_cb.reg_video)
+ {
+ APPL_TRACE_ERROR0("Already registered");
+ sts = BTA_AV_FAIL;
+ }
+ }
+ }
+ else if(chnl != BTA_AV_CHNL_AUDIO)
+ {
+ APPL_TRACE_ERROR1("bad channel: %d", chnl);
+ sts = BTA_AV_FAIL;
+ }
+
+ if(sts == BTA_AV_SUCCESS)
+ {
+ for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+ {
+ if(bta_av_cb.p_scb[xx] == NULL)
+ {
+ /* found an empty spot */
+ p_ret = (tBTA_AV_SCB *)GKI_getbuf(sizeof(tBTA_AV_SCB));
+ if(p_ret)
+ {
+ memset(p_ret, 0, sizeof(tBTA_AV_SCB));
+ p_ret->rc_handle = BTA_AV_RC_HANDLE_NONE;
+ p_ret->chnl = chnl;
+ p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl);
+ p_ret->hdi = xx;
+ bta_av_cb.p_scb[xx] = p_ret;
+ }
+ break;
+ }
+ }
+ }
+ return p_ret;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+ tBTA_AV_STR_MSG *p_msg;
+ UINT16 evt = 0;
+ tBTA_AV_SCB *p_scb = NULL;
+
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+ if (event == BTA_AR_AVDT_CONN_EVT ||
+ event == AVDT_CONNECT_IND_EVT || event == AVDT_DISCONNECT_IND_EVT)
+#else
+ if (event == AVDT_CONNECT_IND_EVT || event == AVDT_DISCONNECT_IND_EVT)
+#endif
+ {
+ evt = BTA_AV_SIG_CHG_EVT;
+ if(AVDT_DISCONNECT_IND_EVT == event)
+ p_scb = bta_av_addr_to_scb(bd_addr);
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+ else if (AVDT_CONNECT_IND_EVT == event)
+ {
+ APPL_TRACE_DEBUG1("CONN_IND is ACP:%d", p_data->hdr.err_param);
+ }
+#endif
+
+ if (/*((p_scb && (p_scb->role & BTA_AV_ROLE_AD_ACP)) ||
+
+ //(AVDT_CONNECT_IND_EVT == event && AVDT_ACP == p_data->hdr.err_param))
+
+ (AVDT_CONNECT_IND_EVT == event))&& */
+ (p_msg = (tBTA_AV_STR_MSG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_STR_MSG)))) != NULL)
+ {
+ p_msg->hdr.event = evt;
+ p_msg->hdr.layer_specific = event;
+ p_msg->hdr.offset = p_data->hdr.err_param;
+ bdcpy(p_msg->bd_addr, bd_addr);
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+ if(p_scb)
+ {
+ APPL_TRACE_DEBUG2("scb hndl x%x, role x%x", p_scb->hndl, p_scb->role);
+ }
+#endif
+ APPL_TRACE_DEBUG6("conn_cback bd_addr:%02x-%02x-%02x-%02x-%02x-%02x",
+ bd_addr[0], bd_addr[1],
+ bd_addr[2], bd_addr[3],
+ bd_addr[4], bd_addr[5]);
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+
+}
+
+#if AVDT_REPORTING == TRUE
+/*******************************************************************************
+**
+** Function bta_av_a2dp_report_cback
+**
+** Description A2DP report callback.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_a2dp_report_cback(UINT8 handle, AVDT_REPORT_TYPE type,
+ tAVDT_REPORT_DATA *p_data)
+{
+ /* Do not need to handle report data for now.
+ * This empty function is here for conformance reasons. */
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_av_api_register
+**
+** Description allocate stream control block,
+** register the service to stack
+** create SDP record
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_api_register(tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_REGISTER registr;
+ tBTA_AV_SCB *p_scb; /* stream control block */
+ tAVDT_REG reg;
+ tAVDT_CS cs;
+ char *p_service_name;
+ tBTA_AV_CODEC codec_type;
+ tBTA_UTL_COD cod;
+ UINT8 index = 0;
+
+ memset(&cs,0,sizeof(tAVDT_CS));
+
+ registr.status = BTA_AV_FAIL_RESOURCES;
+ registr.app_id = p_data->api_reg.app_id;
+ registr.chnl = (tBTA_AV_CHNL)p_data->hdr.layer_specific;
+ do
+ {
+ p_scb = bta_av_alloc_scb(registr.chnl);
+ if(p_scb == NULL)
+ {
+ APPL_TRACE_ERROR0("failed to alloc SCB");
+ break;
+ }
+
+ registr.hndl = p_scb->hndl;
+ p_scb->app_id = registr.app_id;
+
+ /* initialize the stream control block */
+ p_scb->timer.p_cback = (TIMER_CBACK*)&bta_av_timer_cback;
+ registr.status = BTA_AV_SUCCESS;
+
+ if((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0)
+ {
+ /* the first channel registered. register to AVDTP */
+ reg.ctrl_mtu = p_bta_av_cfg->sig_mtu;
+ reg.ret_tout = BTA_AV_RET_TOUT;
+ reg.sig_tout = BTA_AV_SIG_TOUT;
+ reg.idle_tout = BTA_AV_IDLE_TOUT;
+ reg.sec_mask = bta_av_cb.sec_mask;
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+ bta_ar_reg_avdt(®, bta_av_conn_cback, BTA_ID_AV);
+#endif
+ bta_sys_role_chg_register(&bta_av_sys_rs_cback);
+
+ /* create remote control TG service if required */
+ if (bta_av_cb.features & (BTA_AV_FEAT_RCTG))
+ {
+ /* register with no authorization; let AVDTP use authorization instead */
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE)
+ bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+ bta_av_cb.sec_mask, BTA_ID_AV);
+#else
+ bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+ (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV);
+#endif
+
+ bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", NULL,
+ p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV);
+#endif
+ }
+
+ /* Set the Capturing service class bit */
+ cod.service = BTM_COD_SERVICE_CAPTURING;
+ utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+ } /* if 1st channel */
+
+ /* get stream configuration and create stream */
+ /* memset(&cs.cfg,0,sizeof(tAVDT_CFG)); */
+ cs.cfg.num_codec = 1;
+ cs.tsep = AVDT_TSEP_SRC;
+
+ /*
+ * memset of cs takes care setting call back pointers to null.
+ cs.p_data_cback = NULL;
+ cs.p_report_cback = NULL;
+ */
+ cs.nsc_mask = AVDT_NSC_RECONFIG |
+ ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY);
+ APPL_TRACE_DEBUG1("nsc_mask: 0x%x", cs.nsc_mask);
+
+ if (p_data->api_reg.p_service_name[0] == 0)
+ {
+ p_service_name = NULL;
+ }
+ else
+ {
+ p_service_name = p_data->api_reg.p_service_name;
+ }
+
+ p_scb->suspend_sup = TRUE;
+ p_scb->recfg_sup = TRUE;
+
+ cs.p_ctrl_cback = bta_av_dt_cback[p_scb->hdi];
+ if(registr.chnl == BTA_AV_CHNL_AUDIO)
+ {
+ /* set up the audio stream control block */
+ p_scb->p_act_tbl = (const tBTA_AV_ACT *)bta_av_a2d_action;
+ p_scb->p_cos = &bta_av_a2d_cos;
+ p_scb->media_type= AVDT_MEDIA_AUDIO;
+ cs.cfg.psc_mask = AVDT_PSC_TRANS;
+ cs.media_type = AVDT_MEDIA_AUDIO;
+ cs.mtu = p_bta_av_cfg->audio_mtu;
+ cs.flush_to = L2CAP_DEFAULT_FLUSH_TO;
+#if AVDT_REPORTING == TRUE
+ if(bta_av_cb.features & BTA_AV_FEAT_REPORT)
+ {
+ cs.cfg.psc_mask |= AVDT_PSC_REPORT;
+ cs.p_report_cback = bta_av_a2dp_report_cback;
+#if AVDT_MULTIPLEXING == TRUE
+ cs.cfg.mux_tsid_report = 2;
+#endif
+ }
+#endif
+ if(bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT)
+ cs.cfg.psc_mask |= AVDT_PSC_DELAY_RPT;
+
+ /* keep the configuration in the stream control block */
+ memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
+ while(index < BTA_AV_MAX_SEPS &&
+ (*bta_av_a2d_cos.init)(&codec_type, cs.cfg.codec_info,
+ &cs.cfg.num_protect, cs.cfg.protect_info, index) == TRUE)
+ {
+ if(AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS)
+ {
+ p_scb->seps[index].codec_type = codec_type;
+ APPL_TRACE_DEBUG3("audio[%d] av_handle: %d codec_type: %d",
+ index, p_scb->seps[index].av_handle, p_scb->seps[index].codec_type);
+ index++;
+ }
+ else
+ break;
+ }
+
+ if(!bta_av_cb.reg_audio)
+ {
+ /* create the SDP records on the 1st audio channel */
+ bta_av_cb.sdp_a2d_handle = SDP_CreateRecord();
+ A2D_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
+ A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_handle);
+ bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+
+ /* start listening when A2DP is registered */
+ if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
+ bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+
+ /* if the AV and AVK are both supported, it cannot support the CT role */
+ if (bta_av_cb.features & (BTA_AV_FEAT_RCCT))
+ {
+ /* if TG is not supported, we need to register to AVCT now */
+ if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0)
+ {
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE)
+ bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+ bta_av_cb.sec_mask, BTA_ID_AV);
+#else
+ bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+ (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV);
+#endif
+#endif
+ }
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+ /* create an SDP record as AVRC CT. */
+ bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
+ p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV);
+#endif
+ }
+ }
+ bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+ APPL_TRACE_DEBUG1("reg_audio: 0x%x",bta_av_cb.reg_audio);
+ }
+ else
+ {
+ bta_av_cb.reg_video = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+ bta_av_cb.sdp_vdp_handle = SDP_CreateRecord();
+ /* register the video channel */
+ /* no need to verify the function pointer here. it's verified prior */
+ (*p_bta_av_cfg->p_reg)(&cs, p_service_name, p_scb);
+ }
+ } while (0);
+
+ /* call callback with register event */
+ (*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV *)®istr);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_api_deregister
+**
+** Description de-register a channel
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_api_deregister(tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
+
+ if(p_scb)
+ {
+ p_scb->deregistring = TRUE;
+ bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, p_data);
+ }
+ else
+ {
+ bta_av_dereg_comp(p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_ci_data
+**
+** Description forward the BTA_AV_CI_SRC_DATA_READY_EVT to stream state machine
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_ci_data(tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_SCB *p_scb;
+ int i;
+ UINT8 chnl = (UINT8)p_data->hdr.layer_specific;
+
+ for( i=0; i < BTA_AV_NUM_STRS; i++ )
+ {
+ p_scb = bta_av_cb.p_scb[i];
+
+ if(p_scb && p_scb->chnl == chnl)
+ {
+ bta_av_ssm_execute(p_scb, BTA_AV_SRC_DATA_READY_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_rpc_conn
+**
+** Description report report channel open
+**
+** Returns void
+**
+*******************************************************************************/
+#if (AVDT_REPORTING == TRUE)
+
+static void bta_av_rpc_conn(tBTA_AV_DATA *p_data)
+{
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_av_api_to_ssm
+**
+** Description forward the API request to stream state machine
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_api_to_ssm(tBTA_AV_DATA *p_data)
+{
+ int xx;
+ UINT16 event = p_data->hdr.event - BTA_AV_FIRST_A2S_API_EVT + BTA_AV_FIRST_A2S_SSM_EVT;
+
+ for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+ {
+ bta_av_ssm_execute(bta_av_cb.p_scb[xx], event, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_chk_start
+**
+** Description if this is audio channel, check if more than one audio
+** channel is connected & already started.
+**
+** Returns TRUE, if need api_start
+**
+*******************************************************************************/
+BOOLEAN bta_av_chk_start(tBTA_AV_SCB *p_scb)
+{
+ BOOLEAN start = FALSE;
+ tBTA_AV_SCB *p_scbi;
+ int i;
+
+ if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
+ {
+ if ((bta_av_cb.audio_open_cnt >= 2) &&
+ ((0 == (p_scb->role & BTA_AV_ROLE_AD_ACP)) || /* Outgoing connection or */
+ (bta_av_cb.features & BTA_AV_FEAT_ACP_START))) /* auto-starting option */
+ {
+ /* more than one audio channel is connected */
+ /* if this is the 2nd stream as ACP, give INT a chance to issue the START command */
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scbi = bta_av_cb.p_scb[i];
+ if(p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started)
+ {
+ start = TRUE;
+ /* may need to update the flush timeout of this already started stream */
+ if(p_scbi->co_started != bta_av_cb.audio_open_cnt)
+ {
+ p_scbi->co_started = bta_av_cb.audio_open_cnt;
+ L2CA_SetFlushTimeout(p_scbi->peer_addr, p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1] );
+ }
+ }
+ }
+ }
+ }
+ return start;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_restore_switch
+**
+** Description assume that the caller of this function already makes
+** sure that there's only one ACL connection left
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_restore_switch (void)
+{
+ tBTA_AV_CB *p_cb = &bta_av_cb;
+ int i;
+ UINT8 mask;
+
+ APPL_TRACE_DEBUG1("reg_audio: 0x%x",bta_av_cb.reg_audio);
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ mask = BTA_AV_HNDL_TO_MSK(i);
+ if (p_cb->conn_audio == mask)
+ {
+ if (p_cb->p_scb[i])
+ {
+ bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_cb->p_scb[i]->peer_addr);
+ }
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sys_rs_cback
+**
+** Description Receives the role change event from dm
+**
+** Returns (BTA_SYS_ROLE_CHANGE, new_role, hci_status, p_bda)
+**
+*******************************************************************************/
+static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ int i;
+ tBTA_AV_SCB *p_scb;
+ tBTA_AV_ROLE_RES *p_buf;
+ UINT8 cur_role;
+ UINT8 peer_idx = 0;
+
+ APPL_TRACE_DEBUG1("bta_av_sys_rs_cback: %d", bta_av_cb.rs_idx);
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ /* loop through all the SCBs to find matching peer addresses and report the role change event */
+ /* note that more than one SCB (a2dp & vdp) maybe waiting for this event */
+ p_scb = bta_av_cb.p_scb[i];
+ if (p_scb && (bdcmp (peer_addr, p_scb->peer_addr) == 0) &&
+ (p_buf = (tBTA_AV_ROLE_RES *) GKI_getbuf(sizeof(tBTA_AV_ROLE_RES))) != NULL)
+ {
+ APPL_TRACE_DEBUG3("new_role:%d, hci_status:x%x hndl: x%x", id, app_id, p_scb->hndl);
+ /*
+ if ((id != BTM_ROLE_MASTER) && (app_id != HCI_SUCCESS))
+ {
+ bta_sys_set_policy(BTA_ID_AV, (HCI_ENABLE_MASTER_SLAVE_SWITCH|HCI_ENABLE_SNIFF_MODE), p_scb->peer_addr);
+ }
+ */
+ p_buf->hdr.event = BTA_AV_ROLE_CHANGE_EVT;
+ p_buf->hdr.layer_specific = p_scb->hndl;
+ p_buf->new_role = id;
+ p_buf->hci_status = app_id;
+ bta_sys_sendmsg(p_buf);
+
+ peer_idx = p_scb->hdi + 1; /* Handle index for the peer_addr */
+ }
+ }
+
+ /* restore role switch policy, if role switch failed */
+ if ((HCI_SUCCESS != app_id) &&
+ (BTM_GetRole (peer_addr, &cur_role) == BTM_SUCCESS) &&
+ (cur_role == BTM_ROLE_SLAVE) )
+ {
+ bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, peer_addr);
+ }
+
+ /* if BTA_AvOpen() was called for other device, which caused the role switch of the peer_addr, */
+ /* we need to continue opening process for the BTA_AvOpen(). */
+ if ((bta_av_cb.rs_idx != 0) && (bta_av_cb.rs_idx != peer_idx))
+ {
+ p_scb = bta_av_cb.p_scb[bta_av_cb.rs_idx - 1];
+ if (p_scb && p_scb->q_tag == BTA_AV_Q_TAG_OPEN)
+ {
+ APPL_TRACE_DEBUG3 ("bta_av_sys_rs_cback: rs_idx(%d), hndl:x%x q_tag: %d",
+ bta_av_cb.rs_idx, p_scb->hndl, p_scb->q_tag);
+
+ if(HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id)
+ p_scb->q_info.open.switch_res = BTA_AV_RS_OK;
+ else
+ p_scb->q_info.open.switch_res = BTA_AV_RS_FAIL;
+
+ /* Continue av open process */
+ bta_av_do_disc_a2d (p_scb, (tBTA_AV_DATA *)&(p_scb->q_info.open));
+ }
+
+ bta_av_cb.rs_idx = 0;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sco_chg_cback
+**
+** Description receive & process the SCO connection up/down event from sys.
+** call setup also triggers this callback, to suspend av before sco
+** activity happens, or to resume av once call ends.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8
+ app_id, BD_ADDR peer_addr)
+{
+ tBTA_AV_SCB *p_scb;
+ int i;
+ tBTA_AV_API_STOP stop;
+
+ APPL_TRACE_DEBUG2("bta_av_sco_chg_cback:%d status:%d", id, status);
+ if(id)
+ {
+ bta_av_cb.sco_occupied = TRUE;
+
+ /* either BTA_SYS_SCO_OPEN or BTA_SYS_SCO_CLOSE with remaining active SCO */
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scb = bta_av_cb.p_scb[i];
+
+ if( p_scb && p_scb->co_started && (p_scb->sco_suspend == FALSE))
+ {
+ APPL_TRACE_DEBUG1("suspending scb:%d", i);
+ /* scb is used and started, not suspended automatically */
+ p_scb->sco_suspend = TRUE;
+ stop.flush = FALSE;
+ stop.suspend = TRUE;
+ bta_av_ssm_execute(p_scb, BTA_AV_AP_STOP_EVT, (tBTA_AV_DATA *)&stop);
+ }
+ }
+ }
+ else
+ {
+ bta_av_cb.sco_occupied = FALSE;
+
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scb = bta_av_cb.p_scb[i];
+
+ if( p_scb && p_scb->sco_suspend ) /* scb is used and suspended for SCO */
+ {
+ APPL_TRACE_DEBUG1("starting scb:%d", i);
+ bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_switch_if_needed
+**
+** Description This function checks if there is another existing AV
+** channel that is local as slave role.
+** If so, role switch and remove it from link policy.
+**
+** Returns TRUE, if role switch is done
+**
+*******************************************************************************/
+BOOLEAN bta_av_switch_if_needed(tBTA_AV_SCB *p_scb)
+{
+ UINT8 role;
+ BOOLEAN needed = FALSE;
+ tBTA_AV_SCB *p_scbi;
+ int i;
+ UINT8 mask;
+
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ mask = BTA_AV_HNDL_TO_MSK(i);
+ p_scbi = bta_av_cb.p_scb[i];
+ if( p_scbi && (p_scb->hdi != i) && /* not the original channel */
+ ((bta_av_cb.conn_audio & mask) ||/* connected audio */
+ (bta_av_cb.conn_video & mask)) ) /* connected video */
+ {
+ BTM_GetRole(p_scbi->peer_addr, &role);
+ /* this channel is open - clear the role switch link policy for this link */
+ if(BTM_ROLE_MASTER != role)
+ {
+ if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
+ bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scbi->peer_addr);
+ if (BTM_CMD_STARTED != BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL))
+ {
+ /* can not switch role on SCBI
+ * start the timer on SCB - because this function is ONLY called when SCB gets API_OPEN */
+ bta_sys_start_timer(&p_scb->timer, BTA_AV_AVRC_TIMER_EVT, BTA_AV_RS_TIME_VAL);
+ }
+ needed = TRUE;
+ /* mark the original channel as waiting for RS result */
+ bta_av_cb.rs_idx = p_scb->hdi + 1;
+ break;
+ }
+ }
+ }
+ return needed;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_link_role_ok
+**
+** Description This function checks if the SCB has existing ACL connection
+** If so, check if the link role fits the requirements.
+**
+** Returns TRUE, if role is ok
+**
+*******************************************************************************/
+BOOLEAN bta_av_link_role_ok(tBTA_AV_SCB *p_scb, UINT8 bits)
+{
+ UINT8 role;
+ BOOLEAN is_ok = TRUE;
+ BOOLEAN need_timer = FALSE;
+
+ if (BTM_GetRole(p_scb->peer_addr, &role) == BTM_SUCCESS)
+ {
+ APPL_TRACE_ERROR5("bta_av_link_role_ok hndl:x%x role:%d, conn_audio:x%x, bits:%d, features:x%x", p_scb->hndl, role, bta_av_cb.conn_audio, bits, bta_av_cb.features);
+ if (BTM_ROLE_MASTER != role && (A2D_BitsSet(bta_av_cb.conn_audio) > bits || (bta_av_cb.features & BTA_AV_FEAT_MASTER)))
+ {
+ if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
+ bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scb->peer_addr);
+
+ if (BTM_CMD_STARTED != BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL))
+ {
+ /* can not switch role on SCB - start the timer on SCB */
+ need_timer = TRUE;
+ }
+ is_ok = FALSE;
+ p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_START;
+
+ }
+ }
+
+ return is_ok;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_chk_mtu
+**
+** Description if this is audio channel, check if more than one audio
+** channel is connected.
+**
+** Returns The smallest mtu of the connected audio channels
+**
+*******************************************************************************/
+UINT16 bta_av_chk_mtu(tBTA_AV_SCB *p_scb, UINT16 mtu)
+{
+ UINT16 ret_mtu = BTA_AV_MAX_A2DP_MTU;
+ tBTA_AV_SCB *p_scbi;
+ int i;
+ UINT8 mask;
+
+ /* TODO_MV mess with the mtu according to the number of EDR/non-EDR headsets */
+ if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
+ {
+ if(bta_av_cb.audio_open_cnt >= 2)
+ {
+ /* more than one audio channel is connected */
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scbi = bta_av_cb.p_scb[i];
+ if((p_scb != p_scbi) && p_scbi && (p_scbi->chnl == BTA_AV_CHNL_AUDIO) )
+ {
+ mask = BTA_AV_HNDL_TO_MSK(i);
+ APPL_TRACE_DEBUG3("[%d] mtu: %d, mask:0x%x",
+ i, p_scbi->stream_mtu, mask);
+ if(bta_av_cb.conn_audio & mask)
+ {
+ if(ret_mtu > p_scbi->stream_mtu)
+ ret_mtu = p_scbi->stream_mtu;
+ }
+ }
+ }
+ }
+ APPL_TRACE_DEBUG3("bta_av_chk_mtu audio count:%d, conn_audio:0x%x, ret:%d",
+ bta_av_cb.audio_open_cnt, bta_av_cb.conn_audio, ret_mtu);
+ }
+ return ret_mtu;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_dup_audio_buf
+**
+** Description dup the audio data to the q_info.a2d of other audio channels
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_dup_audio_buf(tBTA_AV_SCB *p_scb, BT_HDR *p_buf)
+{
+ tBTA_AV_SCB *p_scbi;
+ BUFFER_Q *pq;
+ int i;
+ UINT16 size, copy_size;
+ BT_HDR *p_new;
+
+ if(!p_buf)
+ return;
+
+ if(bta_av_cb.audio_open_cnt >= 2)
+ {
+ size = GKI_get_buf_size(p_buf);
+ copy_size = BT_HDR_SIZE + p_buf->len + p_buf->offset;
+ /* more than one audio channel is connected */
+ for(i=0; i<BTA_AV_NUM_STRS; i++)
+ {
+ p_scbi = bta_av_cb.p_scb[i];
+ if( (p_scb->hdi != i) && /* not the original channel */
+ (bta_av_cb.conn_audio & BTA_AV_HNDL_TO_MSK(i)) && /* connected audio */
+ p_scbi && p_scbi->co_started ) /* scb is used and started */
+ {
+ /* enqueue the data only when the stream is started */
+ p_new = (BT_HDR *)GKI_getbuf(size);
+ if(p_new)
+ {
+ memcpy(p_new, p_buf, copy_size);
+ pq = &p_scbi->q_info.a2d;
+ GKI_enqueue(pq, p_new);
+ if(pq->count > p_bta_av_cfg->audio_mqs)
+ {
+ bta_av_co_audio_drop(p_scbi->hndl);
+ GKI_freebuf(GKI_dequeue(pq));
+ }
+ }
+ }
+ }
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sm_execute
+**
+** Description State machine event handling function for AV
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_sm_execute(tBTA_AV_CB *p_cb, UINT16 event, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_ST_TBL state_table;
+ UINT8 action;
+
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+ APPL_TRACE_EVENT4("AV event=0x%x(%s) state=%d(%s)",
+ event, bta_av_evt_code(event), p_cb->state, bta_av_st_code(p_cb->state));
+#else
+ APPL_TRACE_EVENT2("AV event=0x%x state=%d", event, p_cb->state);
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_av_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_AV_NEXT_STATE];
+ APPL_TRACE_EVENT1("next state=%d", p_cb->state);
+
+ /* execute action functions */
+ if ((action = state_table[event][BTA_AV_ACTION_COL]) != BTA_AV_IGNORE)
+ {
+ (*bta_av_action[action])(p_cb, p_data);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_av_hdl_event
+**
+** Description Advanced audio/video main event handling function.
+**
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
+{
+ UINT16 event = p_msg->event;
+ UINT16 first_event = BTA_AV_FIRST_NSM_EVT;
+
+ if (event > BTA_AV_LAST_EVT)
+ {
+ return TRUE; /* to free p_msg */
+ }
+
+ if(event >= first_event)
+ {
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+ APPL_TRACE_EVENT2("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event));
+#else
+ APPL_TRACE_EVENT1("AV nsm event=0x%x", event);
+#endif
+ /* non state machine events */
+ (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg);
+ }
+ else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT)
+ {
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+ APPL_TRACE_EVENT2("AV sm event=0x%x(%s)", event, bta_av_evt_code(event));
+#else
+ APPL_TRACE_EVENT1("AV sm event=0x%x", event);
+#endif
+ /* state machine events */
+ bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA *) p_msg);
+ }
+ else
+ {
+ APPL_TRACE_EVENT1("handle=0x%x", p_msg->layer_specific);
+ /* stream state machine events */
+ bta_av_ssm_execute( bta_av_hndl_to_scb(p_msg->layer_specific),
+ p_msg->event, (tBTA_AV_DATA *) p_msg);
+ }
+ return TRUE;
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+/*******************************************************************************
+**
+** Function bta_av_st_code
+**
+** Description
+**
+** Returns char *
+**
+*******************************************************************************/
+static char *bta_av_st_code(UINT8 state)
+{
+ switch(state)
+ {
+ case BTA_AV_INIT_ST: return "INIT";
+ case BTA_AV_OPEN_ST: return "OPEN";
+ default: return "unknown";
+ }
+}
+/*******************************************************************************
+**
+** Function bta_av_evt_code
+**
+** Description
+**
+** Returns char *
+**
+*******************************************************************************/
+char *bta_av_evt_code(UINT16 evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_AV_API_DISABLE_EVT: return "API_DISABLE";
+ case BTA_AV_API_REMOTE_CMD_EVT: return "API_REMOTE_CMD";
+ case BTA_AV_API_VENDOR_CMD_EVT: return "API_VENDOR_CMD";
+ case BTA_AV_API_VENDOR_RSP_EVT: return "API_VENDOR_RSP";
+ case BTA_AV_API_META_RSP_EVT: return "API_META_RSP_EVT";
+ case BTA_AV_API_RC_CLOSE_EVT: return "API_RC_CLOSE";
+ case BTA_AV_AVRC_OPEN_EVT: return "AVRC_OPEN";
+ case BTA_AV_AVRC_MSG_EVT: return "AVRC_MSG";
+ case BTA_AV_AVRC_NONE_EVT: return "AVRC_NONE";
+
+ case BTA_AV_API_OPEN_EVT: return "API_OPEN";
+ case BTA_AV_API_CLOSE_EVT: return "API_CLOSE";
+ case BTA_AV_AP_START_EVT: return "AP_START";
+ case BTA_AV_AP_STOP_EVT: return "AP_STOP";
+ case BTA_AV_API_RECONFIG_EVT: return "API_RECONFIG";
+ case BTA_AV_API_PROTECT_REQ_EVT: return "API_PROTECT_REQ";
+ case BTA_AV_API_PROTECT_RSP_EVT: return "API_PROTECT_RSP";
+ case BTA_AV_API_RC_OPEN_EVT: return "API_RC_OPEN";
+ case BTA_AV_SRC_DATA_READY_EVT: return "SRC_DATA_READY";
+ case BTA_AV_CI_SETCONFIG_OK_EVT: return "CI_SETCONFIG_OK";
+ case BTA_AV_CI_SETCONFIG_FAIL_EVT: return "CI_SETCONFIG_FAIL";
+ case BTA_AV_SDP_DISC_OK_EVT: return "SDP_DISC_OK";
+ case BTA_AV_SDP_DISC_FAIL_EVT: return "SDP_DISC_FAIL";
+ case BTA_AV_STR_DISC_OK_EVT: return "STR_DISC_OK";
+ case BTA_AV_STR_DISC_FAIL_EVT: return "STR_DISC_FAIL";
+ case BTA_AV_STR_GETCAP_OK_EVT: return "STR_GETCAP_OK";
+ case BTA_AV_STR_GETCAP_FAIL_EVT: return "STR_GETCAP_FAIL";
+ case BTA_AV_STR_OPEN_OK_EVT: return "STR_OPEN_OK";
+ case BTA_AV_STR_OPEN_FAIL_EVT: return "STR_OPEN_FAIL";
+ case BTA_AV_STR_START_OK_EVT: return "STR_START_OK";
+ case BTA_AV_STR_START_FAIL_EVT: return "STR_START_FAIL";
+ case BTA_AV_STR_CLOSE_EVT: return "STR_CLOSE";
+ case BTA_AV_STR_CONFIG_IND_EVT: return "STR_CONFIG_IND";
+ case BTA_AV_STR_SECURITY_IND_EVT: return "STR_SECURITY_IND";
+ case BTA_AV_STR_SECURITY_CFM_EVT: return "STR_SECURITY_CFM";
+ case BTA_AV_STR_WRITE_CFM_EVT: return "STR_WRITE_CFM";
+ case BTA_AV_STR_SUSPEND_CFM_EVT: return "STR_SUSPEND_CFM";
+ case BTA_AV_STR_RECONFIG_CFM_EVT: return "STR_RECONFIG_CFM";
+ case BTA_AV_AVRC_TIMER_EVT: return "AVRC_TIMER";
+ case BTA_AV_AVDT_CONNECT_EVT: return "AVDT_CONNECT";
+ case BTA_AV_AVDT_DISCONNECT_EVT: return "AVDT_DISCONNECT";
+ case BTA_AV_ROLE_CHANGE_EVT: return "ROLE_CHANGE";
+ case BTA_AV_AVDT_DELAY_RPT_EVT: return "AVDT_DELAY_RPT";
+ case BTA_AV_ACP_CONNECT_EVT: return "ACP_CONNECT";
+
+ case BTA_AV_API_ENABLE_EVT: return "API_ENABLE";
+ case BTA_AV_API_REGISTER_EVT: return "API_REG";
+ case BTA_AV_API_DEREGISTER_EVT: return "API_DEREG";
+ case BTA_AV_API_DISCONNECT_EVT: return "API_DISCNT";
+ case BTA_AV_CI_SRC_DATA_READY_EVT: return "CI_DATA_READY";
+ case BTA_AV_SIG_CHG_EVT: return "SIG_CHG";
+ case BTA_AV_SIG_TIMER_EVT: return "SIG_TMR";
+ case BTA_AV_SDP_AVRC_DISC_EVT: return "SDP_AVRC_DISC";
+ case BTA_AV_AVRC_CLOSE_EVT: return "AVRC_CLOSE";
+ case BTA_AV_CONN_CHG_EVT: return "CONN_CHG";
+ case BTA_AV_DEREG_COMP_EVT: return "DEREG_COMP";
+#if (AVDT_REPORTING == TRUE)
+ case BTA_AV_AVDT_RPT_CONN_EVT: return "RPT_CONN";
+#endif
+ case BTA_AV_API_START_EVT: return "API_START";
+ case BTA_AV_API_STOP_EVT: return "API_STOP";
+ default: return "unknown";
+ }
+}
+#endif
+
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/av/bta_av_sbc.c b/bta/av/bta_av_sbc.c
new file mode 100644
index 0000000..1517270
--- /dev/null
+++ b/bta/av/bta_av_sbc.c
@@ -0,0 +1,590 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This module contains utility functions for dealing with SBC data frames
+ * and codec capabilities.
+ *
+ ******************************************************************************/
+
+#include "a2d_api.h"
+#include "a2d_sbc.h"
+#include "bta_av_sbc.h"
+
+typedef int (tBTA_AV_SBC_ACT)(void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret);
+
+typedef struct
+{
+ INT32 cur_pos; /* current position */
+ UINT32 src_sps; /* samples per second (source audio data) */
+ UINT32 dst_sps; /* samples per second (converted audio data) */
+ tBTA_AV_SBC_ACT *p_act; /* the action function to do the conversion */
+ UINT16 bits; /* number of bits per pcm sample */
+ UINT16 n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */
+ INT16 worker1;
+ INT16 worker2;
+ UINT8 div;
+} tBTA_AV_SBC_UPS_CB;
+
+tBTA_AV_SBC_UPS_CB bta_av_sbc_ups_cb;
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_init_up_sample
+**
+** Description initialize the up sample
+**
+** src_sps: samples per second (source audio data)
+** dst_sps: samples per second (converted audio data)
+** bits: number of bits per pcm sample
+** n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns none
+**
+*******************************************************************************/
+void bta_av_sbc_init_up_sample (UINT32 src_sps, UINT32 dst_sps, UINT16 bits, UINT16 n_channels)
+{
+ bta_av_sbc_ups_cb.cur_pos = -1;
+ bta_av_sbc_ups_cb.src_sps = src_sps;
+ bta_av_sbc_ups_cb.dst_sps = dst_sps;
+ bta_av_sbc_ups_cb.bits = bits;
+ bta_av_sbc_ups_cb.n_channels= n_channels;
+
+ if(n_channels == 1)
+ {
+ /* mono */
+ if(bits == 8)
+ {
+ bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_8m;
+ bta_av_sbc_ups_cb.div = 1;
+ }
+ else
+ {
+ bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_16m;
+ bta_av_sbc_ups_cb.div = 2;
+ }
+ }
+ else
+ {
+ /* stereo */
+ if(bits == 8)
+ {
+ bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_8s;
+ bta_av_sbc_ups_cb.div = 2;
+ }
+ else
+ {
+ bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_16s;
+ bta_av_sbc_ups_cb.div = 4;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (number of bytes)
+** dst_samples: The size of p_dst (number of bytes)
+**
+** Note: An AE reported an issue with this function.
+** When called with bta_av_sbc_up_sample(src, uint8_array_dst..)
+** the byte before uint8_array_dst may get overwritten.
+** Using uint16_array_dst avoids the problem.
+** This issue is related to endian-ness and is hard to resolve
+** in a generic manner.
+** **************** Please use uint16 array as dst.
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret)
+{
+ UINT32 src;
+ UINT32 dst;
+
+ if(bta_av_sbc_ups_cb.p_act)
+ {
+ src = src_samples/bta_av_sbc_ups_cb.div;
+ dst = dst_samples/bta_av_sbc_ups_cb.div;
+ return (*bta_av_sbc_ups_cb.p_act)(p_src, p_dst, src, dst, p_ret);
+ }
+ else
+ {
+ *p_ret = 0;
+ return 0;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample_16s (16bits-stereo)
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (in uint of 4 bytes)
+** dst_samples: The size of p_dst (in uint of 4 bytes)
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample_16s (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret)
+{
+ INT16 *p_src_tmp = (INT16 *)p_src;
+ INT16 *p_dst_tmp = (INT16 *)p_dst;
+ INT16 *p_worker1 = &bta_av_sbc_ups_cb.worker1;
+ INT16 *p_worker2 = &bta_av_sbc_ups_cb.worker2;
+ UINT32 src_sps = bta_av_sbc_ups_cb.src_sps;
+ UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps;
+
+ while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples)
+ {
+ *p_dst_tmp++ = *p_worker1;
+ *p_dst_tmp++ = *p_worker2;
+
+ bta_av_sbc_ups_cb.cur_pos -= src_sps;
+ dst_samples--;
+ }
+
+ bta_av_sbc_ups_cb.cur_pos = dst_sps;
+
+ while (src_samples-- && dst_samples)
+ {
+ *p_worker1 = *p_src_tmp++;
+ *p_worker2 = *p_src_tmp++;
+
+ do
+ {
+ *p_dst_tmp++ = *p_worker1;
+ *p_dst_tmp++ = *p_worker2;
+
+ bta_av_sbc_ups_cb.cur_pos -= src_sps;
+ dst_samples--;
+ } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
+
+ bta_av_sbc_ups_cb.cur_pos += dst_sps;
+ }
+
+ if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps)
+ bta_av_sbc_ups_cb.cur_pos = 0;
+
+ *p_ret = ((char *)p_src_tmp - (char *)p_src);
+ return ((char *)p_dst_tmp - (char *)p_dst);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample_16m (16bits-mono)
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (in uint of 2 bytes)
+** dst_samples: The size of p_dst (in uint of 2 bytes)
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret)
+{
+ INT16 *p_src_tmp = (INT16 *)p_src;
+ INT16 *p_dst_tmp = (INT16 *)p_dst;
+ INT16 *p_worker = &bta_av_sbc_ups_cb.worker1;
+ UINT32 src_sps = bta_av_sbc_ups_cb.src_sps;
+ UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps;
+
+ while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples)
+ {
+ *p_dst_tmp++ = *p_worker;
+ *p_dst_tmp++ = *p_worker;
+
+ bta_av_sbc_ups_cb.cur_pos -= src_sps;
+ dst_samples--;
+ dst_samples--;
+ }
+
+
+ bta_av_sbc_ups_cb.cur_pos = dst_sps;
+
+ while (src_samples-- && dst_samples)
+ {
+ *p_worker = *p_src_tmp++;
+
+ do
+ {
+ *p_dst_tmp++ = *p_worker;
+ *p_dst_tmp++ = *p_worker;
+
+ bta_av_sbc_ups_cb.cur_pos -= src_sps;
+ dst_samples--;
+ dst_samples--;
+
+ } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
+
+ bta_av_sbc_ups_cb.cur_pos += dst_sps;
+ }
+
+ if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps)
+ bta_av_sbc_ups_cb.cur_pos = 0;
+
+ *p_ret = ((char *)p_src_tmp - (char *)p_src);
+ return ((char *)p_dst_tmp - (char *)p_dst);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample_8s (8bits-stereo)
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (in uint of 2 bytes)
+** dst_samples: The size of p_dst (in uint of 2 bytes)
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret)
+{
+ UINT8 *p_src_tmp = (UINT8 *)p_src;
+ INT16 *p_dst_tmp = (INT16 *)p_dst;
+ INT16 *p_worker1 = &bta_av_sbc_ups_cb.worker1;
+ INT16 *p_worker2 = &bta_av_sbc_ups_cb.worker2;
+ UINT32 src_sps = bta_av_sbc_ups_cb.src_sps;
+ UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps;
+
+ while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples)
+ {
+ *p_dst_tmp++ = *p_worker1;
+ *p_dst_tmp++ = *p_worker2;
+
+ bta_av_sbc_ups_cb.cur_pos -= src_sps;
+ dst_samples--;
+ dst_samples--;
+ }
+
+ bta_av_sbc_ups_cb.cur_pos = dst_sps;
+
+ while (src_samples -- && dst_samples)
+ {
+ *p_worker1 = *(UINT8 *)p_src_tmp++;
+ *p_worker1 -= 0x80;
+ *p_worker1 <<= 8;
+ *p_worker2 = *(UINT8 *)p_src_tmp++;
+ *p_worker2 -= 0x80;
+ *p_worker2 <<= 8;
+
+ do
+ {
+ *p_dst_tmp++ = *p_worker1;
+ *p_dst_tmp++ = *p_worker2;
+
+ bta_av_sbc_ups_cb.cur_pos -= src_sps;
+ dst_samples--;
+ dst_samples--;
+ } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
+
+ bta_av_sbc_ups_cb.cur_pos += dst_sps;
+ }
+
+ if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps)
+ bta_av_sbc_ups_cb.cur_pos = 0;
+
+ *p_ret = ((char *)p_src_tmp - (char *)p_src);
+ return ((char *)p_dst_tmp - (char *)p_dst);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample_8m (8bits-mono)
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (number of bytes)
+** dst_samples: The size of p_dst (number of bytes)
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret)
+{
+ UINT8 *p_src_tmp = (UINT8 *)p_src;
+ INT16 *p_dst_tmp = (INT16 *)p_dst;
+ INT16 *p_worker = &bta_av_sbc_ups_cb.worker1;
+ UINT32 src_sps = bta_av_sbc_ups_cb.src_sps;
+ UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps;
+
+ while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples)
+ {
+ *p_dst_tmp++ = *p_worker;
+ *p_dst_tmp++ = *p_worker;
+
+ bta_av_sbc_ups_cb.cur_pos -= src_sps;
+ dst_samples -= 4;
+ }
+
+
+ bta_av_sbc_ups_cb.cur_pos = dst_sps;
+
+ while (src_samples-- && dst_samples)
+ {
+ *p_worker = *(UINT8 *)p_src_tmp++;
+ *p_worker -= 0x80;
+ *p_worker <<= 8;
+
+ do
+ {
+ *p_dst_tmp++ = *p_worker;
+ *p_dst_tmp++ = *p_worker;
+
+ bta_av_sbc_ups_cb.cur_pos -= src_sps;
+ dst_samples -= 4;
+
+ } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
+
+ bta_av_sbc_ups_cb.cur_pos += dst_sps;
+ }
+
+ if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps)
+ bta_av_sbc_ups_cb.cur_pos = 0;
+
+ *p_ret = ((char *)p_src_tmp - (char *)p_src);
+ return ((char *)p_dst_tmp - (char *)p_dst);
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_cfg_for_cap
+**
+** Description Determine the preferred SBC codec configuration for the
+** given codec capabilities. The function is passed the
+** preferred codec configuration and the peer codec
+** capabilities for the stream. The function attempts to
+** match the preferred capabilities with the configuration
+** as best it can. The resulting codec configuration is
+** returned in the same memory used for the capabilities.
+**
+** Returns 0 if ok, nonzero if error.
+** Codec configuration in p_cap.
+**
+*******************************************************************************/
+UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC_CIE *p_pref)
+{
+ UINT8 status = A2D_SUCCESS;
+ tA2D_SBC_CIE peer_cie;
+
+ /* parse peer capabilities */
+ if ((status = A2D_ParsSbcInfo(&peer_cie, p_peer, TRUE)) != 0)
+ {
+ return status;
+ }
+
+ /* Check if the peer supports our channel mode */
+ if (peer_cie.ch_mode & p_pref->ch_mode)
+ {
+ peer_cie.ch_mode = p_pref->ch_mode;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: ch_mode(0x%02X) not supported", p_pref->ch_mode);
+ return A2D_FAIL;
+ }
+
+ /* Check if the peer supports our sampling freq */
+ if (peer_cie.samp_freq & p_pref->samp_freq)
+ {
+ peer_cie.samp_freq = p_pref->samp_freq;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: samp_freq(0x%02X) not supported", p_pref->samp_freq);
+ return A2D_FAIL;
+ }
+
+ /* Check if the peer supports our block len */
+ if (peer_cie.block_len & p_pref->block_len)
+ {
+ peer_cie.block_len = p_pref->block_len;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: block_len(0x%02X) not supported", p_pref->block_len);
+ return A2D_FAIL;
+ }
+
+ /* Check if the peer supports our num subbands */
+ if (peer_cie.num_subbands & p_pref->num_subbands)
+ {
+ peer_cie.num_subbands = p_pref->num_subbands;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: num_subbands(0x%02X) not supported", p_pref->num_subbands);
+ return A2D_FAIL;
+ }
+
+ /* Check if the peer supports our alloc method */
+ if (peer_cie.alloc_mthd & p_pref->alloc_mthd)
+ {
+ peer_cie.alloc_mthd = p_pref->alloc_mthd;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: alloc_mthd(0x%02X) not supported", p_pref->alloc_mthd);
+ return A2D_FAIL;
+ }
+
+ /* max bitpool */
+ if (p_pref->max_bitpool != 0 && p_pref->max_bitpool < peer_cie.max_bitpool)
+ {
+ peer_cie.max_bitpool = p_pref->max_bitpool;
+ }
+
+ /* min bitpool */
+ if (p_pref->min_bitpool != 0 && p_pref->min_bitpool > peer_cie.min_bitpool)
+ {
+ peer_cie.min_bitpool = p_pref->min_bitpool;
+ }
+
+ if (status == A2D_SUCCESS)
+ {
+ /* build configuration */
+ A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &peer_cie, p_peer);
+ }
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_cfg_in_cap
+**
+** Description This function checks whether an SBC codec configuration
+** is allowable for the given codec capabilities.
+**
+** Returns 0 if ok, nonzero if error.
+**
+*******************************************************************************/
+UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap)
+{
+ UINT8 status = 0;
+ tA2D_SBC_CIE cfg_cie;
+
+ /* parse configuration */
+ if ((status = A2D_ParsSbcInfo(&cfg_cie, p_cfg, FALSE)) != 0)
+ {
+ return status;
+ }
+
+ /* verify that each parameter is in range */
+
+ /* sampling frequency */
+ if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0)
+ {
+ status = A2D_NS_SAMP_FREQ;
+ }
+ /* channel mode */
+ else if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0)
+ {
+ status = A2D_NS_CH_MODE;
+ }
+ /* block length */
+ else if ((cfg_cie.block_len & p_cap->block_len) == 0)
+ {
+ status = A2D_BAD_BLOCK_LEN;
+ }
+ /* subbands */
+ else if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0)
+ {
+ status = A2D_NS_SUBBANDS;
+ }
+ /* allocation method */
+ else if ((cfg_cie.alloc_mthd & p_cap->alloc_mthd) == 0)
+ {
+ status = A2D_NS_ALLOC_MTHD;
+ }
+ /* max bitpool */
+ else if (cfg_cie.max_bitpool > p_cap->max_bitpool)
+ {
+ status = A2D_NS_MAX_BITPOOL;
+ }
+ /* min bitpool */
+ else if (cfg_cie.min_bitpool < p_cap->min_bitpool)
+ {
+ status = A2D_NS_MIN_BITPOOL;
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_bld_hdr
+**
+** Description This function builds the packet header for MPF1.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_sbc_bld_hdr(BT_HDR *p_buf, UINT16 fr_per_pkt)
+{
+ UINT8 *p;
+
+ p_buf->offset -= BTA_AV_SBC_HDR_SIZE;
+ p = (UINT8 *) (p_buf + 1) + p_buf->offset;
+ p_buf->len += BTA_AV_SBC_HDR_SIZE;
+ A2D_BldSbcMplHdr(p, FALSE, FALSE, FALSE, (UINT8) fr_per_pkt);
+}
+
diff --git a/bta/av/bta_av_ssm.c b/bta/av/bta_av_ssm.c
new file mode 100644
index 0000000..a35a4b0
--- /dev/null
+++ b/bta/av/bta_av_ssm.c
@@ -0,0 +1,599 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the stream state machine for the BTA advanced audio/video.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_av_co.h"
+#include "bta_av_int.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+ BTA_AV_INIT_SST,
+ BTA_AV_INCOMING_SST,
+ BTA_AV_OPENING_SST,
+ BTA_AV_OPEN_SST,
+ BTA_AV_RCFG_SST,
+ BTA_AV_CLOSING_SST
+};
+
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_AV_DO_DISC,
+ BTA_AV_CLEANUP,
+ BTA_AV_FREE_SDB,
+ BTA_AV_CONFIG_IND,
+ BTA_AV_DISCONNECT_REQ,
+ BTA_AV_SECURITY_REQ,
+ BTA_AV_SECURITY_RSP,
+ BTA_AV_SETCONFIG_RSP,
+ BTA_AV_ST_RC_TIMER,
+ BTA_AV_STR_OPENED,
+ BTA_AV_SECURITY_IND,
+ BTA_AV_SECURITY_CFM,
+ BTA_AV_DO_CLOSE,
+ BTA_AV_CONNECT_REQ,
+ BTA_AV_SDP_FAILED,
+ BTA_AV_DISC_RESULTS,
+ BTA_AV_DISC_RES_AS_ACP,
+ BTA_AV_OPEN_FAILED,
+ BTA_AV_GETCAP_RESULTS,
+ BTA_AV_SETCONFIG_REJ,
+ BTA_AV_DISCOVER_REQ,
+ BTA_AV_CONN_FAILED,
+ BTA_AV_DO_START,
+ BTA_AV_STR_STOPPED,
+ BTA_AV_RECONFIG,
+ BTA_AV_DATA_PATH,
+ BTA_AV_START_OK,
+ BTA_AV_START_FAILED,
+ BTA_AV_STR_CLOSED,
+ BTA_AV_CLR_CONG,
+ BTA_AV_SUSPEND_CFM,
+ BTA_AV_RCFG_STR_OK,
+ BTA_AV_RCFG_FAILED,
+ BTA_AV_RCFG_CONNECT,
+ BTA_AV_RCFG_DISCNTD,
+ BTA_AV_SUSPEND_CONT,
+ BTA_AV_RCFG_CFM,
+ BTA_AV_RCFG_OPEN,
+ BTA_AV_SECURITY_REJ,
+ BTA_AV_OPEN_RC,
+ BTA_AV_CHK_2ND_START,
+ BTA_AV_SAVE_CAPS,
+ BTA_AV_SET_USE_RC,
+ BTA_AV_CCO_CLOSE,
+ BTA_AV_SWITCH_ROLE,
+ BTA_AV_ROLE_RES,
+ BTA_AV_DELAY_CO,
+ BTA_AV_OPEN_AT_INC,
+ BTA_AV_NUM_SACTIONS
+};
+
+#define BTA_AV_SIGNORE BTA_AV_NUM_SACTIONS
+
+
+/* state table information */
+/* #define BTA_AV_SACTION_COL 0 position of actions */
+#define BTA_AV_SACTIONS 2 /* number of actions */
+#define BTA_AV_SNEXT_STATE 2 /* position of next state */
+#define BTA_AV_NUM_COLS 3 /* number of columns in state tables */
+
+/* state table for init state */
+static const UINT8 bta_av_sst_init[][BTA_AV_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* AP_OPEN_EVT */ {BTA_AV_DO_DISC, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* AP_CLOSE_EVT */ {BTA_AV_CLEANUP, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* API_PROTECT_REQ_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* API_PROTECT_RSP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_DISC_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_GETCAP_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_GETCAP_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_OPEN_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_OPEN_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_CLOSE_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_SECURITY_IND_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* AVDT_DISCONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* AVDT_DELAY_RPT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST }
+};
+
+/* state table for incoming state */
+static const UINT8 bta_av_sst_incoming[][BTA_AV_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* AP_OPEN_EVT */ {BTA_AV_OPEN_AT_INC, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* AP_CLOSE_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_DISCONNECT_REQ, BTA_AV_CLOSING_SST },
+/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SETCONFIG_RSP, BTA_AV_ST_RC_TIMER, BTA_AV_INCOMING_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SETCONFIG_RSP, BTA_AV_CLEANUP, BTA_AV_INIT_SST },
+/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_DISC_OK_EVT */ {BTA_AV_DISC_RES_AS_ACP,BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_DISC_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_GETCAP_OK_EVT */ {BTA_AV_SAVE_CAPS, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_GETCAP_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_OPEN_OK_EVT */ {BTA_AV_STR_OPENED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_OPEN_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_CLOSE_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_CLEANUP, BTA_AV_INIT_SST },
+/* STR_CONFIG_IND_EVT */ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* AVDT_DISCONNECT_EVT */ {BTA_AV_CCO_CLOSE, BTA_AV_CLEANUP, BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST }
+};
+
+/* state table for opening state */
+static const UINT8 bta_av_sst_opening[][BTA_AV_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* AP_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* SDP_DISC_OK_EVT */ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* SDP_DISC_FAIL_EVT */ {BTA_AV_CONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_DISC_OK_EVT */ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_DISC_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_GETCAP_OK_EVT */ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_GETCAP_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_OPEN_OK_EVT */ {BTA_AV_ST_RC_TIMER, BTA_AV_STR_OPENED, BTA_AV_OPEN_SST },
+/* STR_OPEN_FAIL_EVT */ {BTA_AV_OPEN_FAILED, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_CLOSE_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_CONFIG_IND_EVT */ {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST },
+/* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* AVRC_TIMER_EVT */ {BTA_AV_SWITCH_ROLE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* AVDT_CONNECT_EVT */ {BTA_AV_DISCOVER_REQ, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* AVDT_DISCONNECT_EVT */ {BTA_AV_CONN_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/ {BTA_AV_ROLE_RES, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_OPENING_SST },
+/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPENING_SST }
+};
+
+/* state table for open state */
+static const UINT8 bta_av_sst_open[][BTA_AV_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* AP_CLOSE_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AP_START_EVT */ {BTA_AV_DO_START, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* AP_STOP_EVT */ {BTA_AV_STR_STOPPED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* API_RECONFIG_EVT */ {BTA_AV_RECONFIG, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* API_PROTECT_REQ_EVT */ {BTA_AV_SECURITY_REQ, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* API_PROTECT_RSP_EVT */ {BTA_AV_SECURITY_RSP, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* API_RC_OPEN_EVT */ {BTA_AV_SET_USE_RC, BTA_AV_OPEN_RC, BTA_AV_OPEN_SST },
+/* SRC_DATA_READY_EVT */ {BTA_AV_DATA_PATH, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_DISC_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_GETCAP_OK_EVT */ {BTA_AV_SAVE_CAPS, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_GETCAP_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_OPEN_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_OPEN_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_START_OK_EVT */ {BTA_AV_START_OK, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_START_FAIL_EVT */ {BTA_AV_START_FAILED, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_CLOSE_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_IND, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_SECURITY_CFM_EVT */ {BTA_AV_SECURITY_CFM, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_WRITE_CFM_EVT */ {BTA_AV_CLR_CONG, BTA_AV_DATA_PATH, BTA_AV_OPEN_SST },
+/* STR_SUSPEND_CFM_EVT */ {BTA_AV_SUSPEND_CFM, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* AVRC_TIMER_EVT */ {BTA_AV_OPEN_RC, BTA_AV_CHK_2ND_START, BTA_AV_OPEN_SST },
+/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* AVDT_DISCONNECT_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/ {BTA_AV_ROLE_RES, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_OPEN_SST }
+};
+
+/* state table for reconfig state */
+static const UINT8 bta_av_sst_rcfg[][BTA_AV_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* AP_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* API_PROTECT_REQ_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* API_PROTECT_RSP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* SDP_DISC_OK_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* SDP_DISC_FAIL_EVT */ {BTA_AV_FREE_SDB, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_DISC_OK_EVT */ {BTA_AV_DISC_RESULTS, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_DISC_FAIL_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_GETCAP_OK_EVT */ {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_GETCAP_FAIL_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_OPEN_OK_EVT */ {BTA_AV_RCFG_STR_OK, BTA_AV_SIGNORE, BTA_AV_OPEN_SST },
+/* STR_OPEN_FAIL_EVT */ {BTA_AV_RCFG_FAILED, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_CLOSE_EVT */ {BTA_AV_RCFG_CONNECT, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_SECURITY_IND_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_SUSPEND_CFM_EVT */ {BTA_AV_SUSPEND_CONT, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* STR_RECONFIG_CFM_EVT */ {BTA_AV_RCFG_CFM, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* AVDT_CONNECT_EVT */ {BTA_AV_RCFG_OPEN, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* AVDT_DISCONNECT_EVT */ {BTA_AV_RCFG_DISCNTD, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* AVDT_DELAY_RPT_EVT */ {BTA_AV_DELAY_CO, BTA_AV_SIGNORE, BTA_AV_RCFG_SST },
+/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_RCFG_SST }
+};
+
+/* state table for closing state */
+static const UINT8 bta_av_sst_closing[][BTA_AV_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* AP_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AP_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AP_START_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AP_STOP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* API_RECONFIG_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* API_PROTECT_REQ_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* API_PROTECT_RSP_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* API_RC_OPEN_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* SRC_DATA_READY_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* CI_SETCONFIG_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* SDP_DISC_OK_EVT */ {BTA_AV_SDP_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* SDP_DISC_FAIL_EVT */ {BTA_AV_SDP_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* STR_DISC_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_DISC_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_GETCAP_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_GETCAP_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_OPEN_OK_EVT */ {BTA_AV_DO_CLOSE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_OPEN_FAIL_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_START_OK_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_CLOSE_EVT */ {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_CONFIG_IND_EVT */ {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_SECURITY_IND_EVT */ {BTA_AV_SECURITY_REJ, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_SECURITY_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_WRITE_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_SUSPEND_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* STR_RECONFIG_CFM_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AVRC_TIMER_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AVDT_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AVDT_DISCONNECT_EVT */ {BTA_AV_STR_CLOSED, BTA_AV_SIGNORE, BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* AVDT_DELAY_RPT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST },
+/* ACP_CONNECT_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_CLOSING_SST }
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_AV_SST_TBL)[BTA_AV_NUM_COLS];
+
+/* state table */
+static const tBTA_AV_SST_TBL bta_av_sst_tbl[] =
+{
+ bta_av_sst_init,
+ bta_av_sst_incoming,
+ bta_av_sst_opening,
+ bta_av_sst_open,
+ bta_av_sst_rcfg,
+ bta_av_sst_closing
+};
+
+
+
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+static char *bta_av_sst_code(UINT8 state);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_av_is_rcfg_sst
+**
+** Description Check if stream state machine is in reconfig state.
+**
+**
+** Returns TRUE if stream state machine is in reconfig state.
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_rcfg_sst (tBTA_AV_SCB *p_scb)
+{
+ BOOLEAN is_rcfg_sst = FALSE;
+
+ if (p_scb != NULL)
+ {
+ if (p_scb->state == BTA_AV_RCFG_SST)
+ is_rcfg_sst = TRUE;
+ }
+
+ return is_rcfg_sst;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_ssm_execute
+**
+** Description Stream state machine event handling function for AV
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data)
+{
+ tBTA_AV_SST_TBL state_table;
+ UINT8 action;
+ int i, xx;
+
+ if(p_scb == NULL)
+ {
+ /* this stream is not registered */
+ APPL_TRACE_EVENT0("AV channel not registered");
+ return;
+ }
+
+ /* In case incoming connection is for VDP, we need to swap scb. */
+ /* When ACP_CONNECT_EVT was received, we put first available scb to */
+ /* to Incoming state. Later, when STR_CONFIG_IND_EVT is coming, we */
+ /* know if it is A2DP or VDP. */
+ if ((p_scb->state == BTA_AV_INIT_SST) && (event == BTA_AV_STR_CONFIG_IND_EVT))
+ {
+ for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+ {
+ if (bta_av_cb.p_scb[xx])
+ {
+ if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST)
+ {
+ bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
+ bta_av_cb.p_scb[xx]->coll_mask = 0;
+ p_scb->state = BTA_AV_INCOMING_SST;
+ break;
+ }
+ }
+ }
+ }
+
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+ APPL_TRACE_EVENT5("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
+ p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state));
+#else
+ APPL_TRACE_EVENT2("AV Sevent=0x%x state=%d", event, p_scb->state);
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_av_sst_tbl[p_scb->state];
+
+ event -= BTA_AV_FIRST_SSM_EVT;
+
+ /* set next state */
+ p_scb->state = state_table[event][BTA_AV_SNEXT_STATE];
+
+ /* execute action functions */
+ for(i=0; i< BTA_AV_SACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_AV_SIGNORE)
+ {
+ (*p_scb->p_act_tbl[action])(p_scb, p_data);
+ }
+ else
+ break;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_av_is_scb_opening
+**
+** Description Returns TRUE is scb is in opening state.
+**
+**
+** Returns TRUE if scb is in opening state.
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_scb_opening (tBTA_AV_SCB *p_scb)
+{
+ BOOLEAN is_opening = FALSE;
+
+ if (p_scb)
+ {
+ if (p_scb->state == BTA_AV_OPENING_SST)
+ is_opening = TRUE;
+ }
+
+ return is_opening;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_is_scb_incoming
+**
+** Description Returns TRUE is scb is in incoming state.
+**
+**
+** Returns TRUE if scb is in incoming state.
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_scb_incoming (tBTA_AV_SCB *p_scb)
+{
+ BOOLEAN is_incoming = FALSE;
+
+ if (p_scb)
+ {
+ if (p_scb->state == BTA_AV_INCOMING_SST)
+ is_incoming = TRUE;
+ }
+
+ return is_incoming;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_set_scb_sst_init
+**
+** Description Set SST state to INIT.
+** Use this function to change SST outside of state machine.
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_av_set_scb_sst_init (tBTA_AV_SCB *p_scb)
+{
+ if (p_scb)
+ {
+ p_scb->state = BTA_AV_INIT_SST;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_av_is_scb_init
+**
+** Description Returns TRUE is scb is in init state.
+**
+**
+** Returns TRUE if scb is in incoming state.
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_scb_init (tBTA_AV_SCB *p_scb)
+{
+ BOOLEAN is_init = FALSE;
+
+ if (p_scb)
+ {
+ if (p_scb->state == BTA_AV_INIT_SST)
+ is_init = TRUE;
+ }
+
+ return is_init;
+}
+
+/*******************************************************************************
+**
+** Function bta_av_set_scb_sst_incoming
+**
+** Description Set SST state to incoming.
+** Use this function to change SST outside of state machine.
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_av_set_scb_sst_incoming (tBTA_AV_SCB *p_scb)
+{
+ if (p_scb)
+ {
+ p_scb->state = BTA_AV_INCOMING_SST;
+ }
+}
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+/*******************************************************************************
+**
+** Function bta_av_sst_code
+**
+** Description
+**
+** Returns char *
+**
+*******************************************************************************/
+static char *bta_av_sst_code(UINT8 state)
+{
+ switch(state)
+ {
+ case BTA_AV_INIT_SST: return "INIT";
+ case BTA_AV_INCOMING_SST: return "INCOMING";
+ case BTA_AV_OPENING_SST: return "OPENING";
+ case BTA_AV_OPEN_SST: return "OPEN";
+ case BTA_AV_RCFG_SST: return "RCFG";
+ case BTA_AV_CLOSING_SST: return "CLOSING";
+ default: return "unknown";
+ }
+}
+
+#endif
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
new file mode 100644
index 0000000..29b4ec2
--- /dev/null
+++ b/bta/dm/bta_dm_act.c
@@ -0,0 +1,4886 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the action functions for device manager state
+ * machine.
+ *
+ ******************************************************************************/
+
+#include "bt_types.h"
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "bta_dm_co.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include "btu.h"
+#include "sdp_api.h"
+#include "l2c_api.h"
+#include "wbt_api.h"
+#include "utl.h"
+#include <string.h>
+
+static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
+static void bta_dm_inq_cmpl_cb (void * p_result);
+static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc, BD_NAME bd_name);
+static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name);
+static void bta_dm_find_services ( BD_ADDR bd_addr);
+static void bta_dm_discover_next_device(void);
+static void bta_dm_sdp_callback (UINT16 sdp_status);
+static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, UINT8 *service_name, UINT8 service_id, BOOLEAN is_originator);
+static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name);
+static UINT8 bta_dm_link_key_request_cback (BD_ADDR bd_addr, LINK_KEY key);
+static UINT8 bta_dm_new_link_key_cback(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, LINK_KEY key, UINT8 key_type);
+static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,BD_NAME bd_name, int result);
+static void bta_dm_local_name_cback(BD_ADDR bd_addr);
+static BOOLEAN bta_dm_check_av(UINT16 event);
+#if (BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
+static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data);
+#else
+static void bta_dm_acl_change_cback (BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn, BD_FEATURES features, BOOLEAN is_new);
+#endif
+static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+/* Extended Inquiry Response */
+static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data);
+
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+static void bta_dm_set_eir (char *local_name);
+#endif /* BTM_EIR_SERVER_INCLUDED */
+
+#if (BTM_EIR_CLIENT_INCLUDED == TRUE)
+static void bta_dm_eir_search_services( tBTM_INQ_RESULTS *p_result,
+ tBTA_SERVICE_MASK *p_services_to_search,
+ tBTA_SERVICE_MASK *p_services_found);
+#endif /* BTM_EIR_CLIENT_INCLUDED */
+
+static void bta_dm_rssi_cback (tBTM_RSSI_RESULTS *p_result);
+static void bta_dm_signal_strength_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_link_quality_cback (tBTM_LINK_QUALITY_RESULTS *p_result);
+static void bta_dm_search_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_disable_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+static void bta_dm_adjust_roles(BOOLEAN delay_role_switch);
+static char *bta_dm_get_remname(void);
+static void bta_dm_bond_cancel_complete_cback(tBTM_STATUS result);
+
+static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr);
+static void bta_dm_discover_device(BD_ADDR remote_bd_addr);
+
+static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status );
+
+static BOOLEAN bta_dm_dev_blacklisted_for_switch (BD_ADDR remote_bd_addr);
+static void bta_dm_delay_role_switch_cback (TIMER_LIST_ENT *p_tle);
+
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+ #if ((defined SMP_INCLUDED) && (SMP_INCLUDED == TRUE))
+static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_DATA *p_data);
+ #endif
+static void bta_dm_ble_id_key_cback (UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key);
+ #if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+static void btm_dm_start_gatt_discovery ( BD_ADDR bd_addr);
+static void bta_dm_cancel_gatt_discovery(BD_ADDR bd_addr);
+static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
+ #endif
+#endif
+
+extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8* p_uuid128);
+
+const UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID] =
+{
+ UUID_SERVCLASS_PNP_INFORMATION, /* Reserved */
+ UUID_SERVCLASS_SERIAL_PORT, /* BTA_SPP_SERVICE_ID */
+ UUID_SERVCLASS_DIALUP_NETWORKING, /* BTA_DUN_SERVICE_ID */
+ UUID_SERVCLASS_AUDIO_SOURCE, /* BTA_A2DP_SOURCE_SERVICE_ID */
+ UUID_SERVCLASS_LAN_ACCESS_USING_PPP, /* BTA_LAP_SERVICE_ID */
+ UUID_SERVCLASS_HEADSET, /* BTA_HSP_HS_SERVICE_ID */
+ UUID_SERVCLASS_HF_HANDSFREE, /* BTA_HFP_HS_SERVICE_ID */
+ UUID_SERVCLASS_OBEX_OBJECT_PUSH, /* BTA_OPP_SERVICE_ID */
+ UUID_SERVCLASS_OBEX_FILE_TRANSFER, /* BTA_FTP_SERVICE_ID */
+ UUID_SERVCLASS_CORDLESS_TELEPHONY, /* BTA_CTP_SERVICE_ID */
+ UUID_SERVCLASS_INTERCOM, /* BTA_ICP_SERVICE_ID */
+ UUID_SERVCLASS_IRMC_SYNC, /* BTA_SYNC_SERVICE_ID */
+ UUID_SERVCLASS_DIRECT_PRINTING, /* BTA_BPP_SERVICE_ID */
+ UUID_SERVCLASS_IMAGING_RESPONDER, /* BTA_BIP_SERVICE_ID */
+ UUID_SERVCLASS_PANU, /* BTA_PANU_SERVICE_ID */
+ UUID_SERVCLASS_NAP, /* BTA_NAP_SERVICE_ID */
+ UUID_SERVCLASS_GN, /* BTA_GN_SERVICE_ID */
+ UUID_SERVCLASS_SAP, /* BTA_SAP_SERVICE_ID */
+ UUID_SERVCLASS_AUDIO_SINK, /* BTA_A2DP_SERVICE_ID */
+ UUID_SERVCLASS_AV_REMOTE_CONTROL, /* BTA_AVRCP_SERVICE_ID */
+ UUID_SERVCLASS_HUMAN_INTERFACE, /* BTA_HID_SERVICE_ID */
+ UUID_SERVCLASS_VIDEO_SINK, /* BTA_VDP_SERVICE_ID */
+ UUID_SERVCLASS_PBAP_PSE, /* BTA_PBAP_SERVICE_ID */
+ UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, /* BTA_HSP_SERVICE_ID */
+ UUID_SERVCLASS_AG_HANDSFREE, /* BTA_HFP_SERVICE_ID */
+ UUID_SERVCLASS_MESSAGE_ACCESS, /* BTA_MAP_SERVICE_ID */
+ UUID_SERVCLASS_MESSAGE_NOTIFICATION, /* BTA_MN_SERVICE_ID */
+ UUID_SERVCLASS_HDP_PROFILE, /* BTA_HDP_SERVICE_ID */
+ UUID_SERVCLASS_PBAP_PCE /* BTA_PCE_SERVICE_ID */
+#if BLE_INCLUDED && BTA_GATT_INCLUDED
+ ,UUID_PROTOCOL_ATT /* BTA_GATT_SERVICE_ID */
+#endif
+};
+
+/*
+ * NOTE : The number of element in bta_service_id_to_btm_srv_id_lkup_tbl should be matching with
+ * the value BTA_MAX_SERVICE_ID in bta_api.h
+ *
+ * i.e., If you add new Service ID for BTA, the correct security ID of the new service
+ * from Security service definitions (btm_api.h) should be added to this lookup table.
+ */
+const UINT32 bta_service_id_to_btm_srv_id_lkup_tbl [BTA_MAX_SERVICE_ID] =
+{
+ 0, /* Reserved */
+ BTM_SEC_SERVICE_SERIAL_PORT, /* BTA_SPP_SERVICE_ID */
+ BTM_SEC_SERVICE_DUN, /* BTA_DUN_SERVICE_ID */
+ BTM_SEC_SERVICE_AVDTP, /* BTA_AUDIO_SOURCE_SERVICE_ID */
+ BTM_SEC_SERVICE_LAN_ACCESS, /* BTA_LAP_SERVICE_ID */
+ BTM_SEC_SERVICE_HEADSET_AG, /* BTA_HSP_SERVICE_ID */
+ BTM_SEC_SERVICE_AG_HANDSFREE, /* BTA_HFP_SERVICE_ID */
+ BTM_SEC_SERVICE_OBEX, /* BTA_OPP_SERVICE_ID */
+ BTM_SEC_SERVICE_OBEX_FTP, /* BTA_FTP_SERVICE_ID */
+ BTM_SEC_SERVICE_CORDLESS, /* BTA_CTP_SERVICE_ID */
+ BTM_SEC_SERVICE_INTERCOM, /* BTA_ICP_SERVICE_ID */
+ BTM_SEC_SERVICE_IRMC_SYNC, /* BTA_SYNC_SERVICE_ID */
+ BTM_SEC_SERVICE_BPP_JOB, /* BTA_BPP_SERVICE_ID */
+ BTM_SEC_SERVICE_BIP, /* BTA_BIP_SERVICE_ID */
+ BTM_SEC_SERVICE_BNEP_PANU, /* BTA_PANU_SERVICE_ID */
+ BTM_SEC_SERVICE_BNEP_NAP, /* BTA_NAP_SERVICE_ID */
+ BTM_SEC_SERVICE_BNEP_GN, /* BTA_GN_SERVICE_ID */
+ BTM_SEC_SERVICE_SAP, /* BTA_SAP_SERVICE_ID */
+ BTM_SEC_SERVICE_AVDTP, /* BTA_A2DP_SERVICE_ID */
+ BTM_SEC_SERVICE_AVCTP, /* BTA_AVRCP_SERVICE_ID */
+ BTM_SEC_SERVICE_HID_SEC_CTRL, /* BTA_HID_SERVICE_ID */
+ BTM_SEC_SERVICE_AVDTP, /* BTA_VDP_SERVICE_ID */
+ BTM_SEC_SERVICE_PBAP, /* BTA_PBAP_SERVICE_ID */
+ BTM_SEC_SERVICE_HEADSET, /* BTA_HSP_HS_SERVICE_ID */
+ BTM_SEC_SERVICE_HF_HANDSFREE, /* BTA_HFP_HS_SERVICE_ID */
+ BTM_SEC_SERVICE_MAP, /* BTA_MAP_SERVICE_ID */
+ BTM_SEC_SERVICE_MAP, /* BTA_MN_SERVICE_ID */
+ BTM_SEC_SERVICE_HDP_SNK, /* BTA_HDP_SERVICE_ID */
+ BTM_SEC_SERVICE_PBAP /* BTA_PCE_SERVICE_ID */
+#if BLE_INCLUDED && BTA_GATT_INCLUDED
+ ,BTM_SEC_SERVICE_ATT /* BTA_GATT_SERVICE_ID */
+#endif
+};
+
+/* bta security callback */
+const tBTM_APPL_INFO bta_security =
+{
+ &bta_dm_authorize_cback,
+ &bta_dm_pin_cback,
+ &bta_dm_new_link_key_cback,
+ &bta_dm_link_key_request_cback,
+ &bta_dm_authentication_complete_cback,
+ NULL,
+ &bta_dm_bond_cancel_complete_cback,
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+ &bta_dm_sp_cback
+#else
+ NULL
+#endif
+#if BLE_INCLUDED == TRUE
+#if SMP_INCLUDED == TRUE
+ ,&bta_dm_ble_smp_cback
+#endif
+ ,&bta_dm_ble_id_key_cback
+#endif
+
+};
+
+/* TBD... To be moved to some conf file..? */
+#define BTA_DM_MAX_ROLE_SWITCH_BLACKLIST_COUNT 5
+const tBTA_DM_LMP_VER_INFO bta_role_switch_blacklist[BTA_DM_MAX_ROLE_SWITCH_BLACKLIST_COUNT] =
+{
+ {0x000F,0x2000,0x04},
+ {0x00,0x00,0x00},
+ {0x00,0x00,0x00},
+ {0x00,0x00,0x00},
+ {0x00,0x00,0x00}
+};
+
+#define MAX_DISC_RAW_DATA_BUF (4096)
+UINT8 g_disc_raw_data_buf[MAX_DISC_RAW_DATA_BUF];
+
+/*******************************************************************************
+**
+** Function bta_dm_app_ready_timer_cback
+**
+** Description allow sending EIR to controller
+**
+**
+** Returns void
+**
+*******************************************************************************/
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+static void bta_dm_app_ready_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+ bta_dm_set_eir (NULL);
+}
+#else
+#define bta_dm_app_ready_timer_cback (x)
+#endif
+
+/*******************************************************************************
+**
+** Function bta_dm_enable
+**
+** Description Initialises the BT device manager
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_enable(tBTA_DM_MSG *p_data)
+{
+ tBTA_SYS_HW_MSG *sys_enable_event;
+ tBTA_DM_SEC sec_event;
+
+
+ /* if already in use, return an error */
+ if( bta_dm_cb.is_bta_dm_active == TRUE )
+ {
+ APPL_TRACE_WARNING0("bta_dm_enable - device already started by another application");
+ memset(&sec_event.enable, 0, sizeof ( tBTA_DM_ENABLE ));
+ sec_event.enable.status = BTA_FAILURE;
+ if( p_data->enable.p_sec_cback != NULL )
+ p_data->enable.p_sec_cback (BTA_DM_ENABLE_EVT, &sec_event);
+ return;
+ }
+
+
+ /* first, register our callback to SYS HW manager */
+ bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
+
+ /* make sure security callback is saved - if no callback, do not erase the previous one,
+ it could be an error recovery mechanism */
+ if( p_data->enable.p_sec_cback != NULL )
+ bta_dm_cb.p_sec_cback = p_data->enable.p_sec_cback;
+ /* notify BTA DM is now active */
+ bta_dm_cb.is_bta_dm_active = TRUE;
+
+ /* send a message to BTA SYS */
+ if ((sys_enable_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+ {
+ sys_enable_event->hdr.event = BTA_SYS_API_ENABLE_EVT;
+ sys_enable_event->hw_module = BTA_SYS_HW_BLUETOOTH;
+
+ bta_sys_sendmsg(sys_enable_event);
+
+ }
+
+
+
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_dm_sys_hw_cback
+**
+** Description callback register to SYS to get HW status updates
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status )
+{
+ DEV_CLASS dev_class;
+ tBTA_DM_SEC_CBACK *temp_cback;
+#if BLE_INCLUDED == TRUE
+ UINT8 key_mask = 0;
+ BT_OCTET16 er;
+ tBTA_BLE_LOCAL_ID_KEYS id_key;
+ tBT_UUID app_uuid = {LEN_UUID_128,{0}};
+#endif
+ APPL_TRACE_DEBUG1(" bta_dm_sys_hw_cback with event: %i" , status );
+
+ /* On H/W error evt, report to the registered DM application callback */
+ if (status == BTA_SYS_HW_ERROR_EVT) {
+ if( bta_dm_cb.p_sec_cback != NULL )
+ bta_dm_cb.p_sec_cback(BTA_DM_HW_ERROR_EVT, NULL);
+ return;
+ }
+ if( status == BTA_SYS_HW_OFF_EVT )
+ {
+ if( bta_dm_cb.p_sec_cback != NULL )
+ bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL);
+
+ /* reinitialize the control block */
+ memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+
+ /* unregister from SYS */
+ bta_sys_hw_unregister( BTA_SYS_HW_BLUETOOTH );
+ /* notify BTA DM is now unactive */
+ bta_dm_cb.is_bta_dm_active = FALSE;
+ }
+ else
+ if( status == BTA_SYS_HW_ON_EVT )
+ {
+ /* FIXME: We should not unregister as the SYS shall invoke this callback on a H/W error.
+ * We need to revisit when this platform has more than one BLuetooth H/W chip */
+ //bta_sys_hw_unregister( BTA_SYS_HW_BLUETOOTH);
+
+ /* save security callback */
+ temp_cback = bta_dm_cb.p_sec_cback;
+ /* make sure the control block is properly initialized */
+ memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+ /* and retrieve the callback */
+ bta_dm_cb.p_sec_cback=temp_cback;
+ bta_dm_cb.is_bta_dm_active = TRUE;
+
+ /* hw is ready, go on with BTA DM initialization */
+ memset(&bta_dm_search_cb, 0x00, sizeof(bta_dm_search_cb));
+ memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
+ memset(&bta_dm_di_cb, 0, sizeof(tBTA_DM_DI_CB));
+
+ memcpy(dev_class, bta_dm_cfg.dev_class, sizeof(dev_class));
+ BTM_SetDeviceClass (dev_class);
+
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+ /* load BLE local information: ID keys, ER if available */
+ bta_dm_co_ble_load_local_keys(&key_mask, er, &id_key);
+
+ if (key_mask & BTA_BLE_LOCAL_KEY_TYPE_ER)
+ {
+ BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ER, (tBTM_BLE_LOCAL_KEYS *)&er);
+ }
+ if (key_mask & BTA_BLE_LOCAL_KEY_TYPE_ID)
+ {
+ BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ID, (tBTM_BLE_LOCAL_KEYS *)&id_key);
+ }
+#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+ memset (&app_uuid.uu.uuid128, 0x87, LEN_UUID_128);
+ BTA_GATTC_AppRegister(&app_uuid, bta_dm_gattc_callback);
+#endif
+#endif
+
+ BTM_SecRegister((tBTM_APPL_INFO*)&bta_security);
+ BTM_SetDefaultLinkSuperTout(bta_dm_cfg.link_timeout);
+ BTM_WritePageTimeout(bta_dm_cfg.page_timeout);
+ bta_dm_cb.cur_policy = bta_dm_cfg.policy_settings;
+ BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
+ BTM_RegBusyLevelNotif (bta_dm_bl_change_cback, NULL, BTM_BL_UPDATE_MASK|BTM_BL_ROLE_CHG_MASK);
+#else
+ BTM_AclRegisterForChanges(bta_dm_acl_change_cback);
+#endif
+ /* Earlier, we used to invoke BTM_ReadLocalAddr which was just copying the bd_addr
+ from the control block and invoking the callback which was sending the DM_ENABLE_EVT.
+ But then we have a few HCI commands being invoked above which were still in progress
+ when the ENABLE_EVT was sent. So modified this to fetch the local name which forces
+ the DM_ENABLE_EVT to be sent only after all the init steps are complete */
+ BTM_ReadLocalDeviceNameFromController((tBTM_CMPL_CB *)bta_dm_local_name_cback);
+
+ bta_sys_rm_register((tBTA_SYS_CONN_CBACK*)bta_dm_rm_cback);
+
+ /* initialize bluetooth low power manager */
+ bta_dm_init_pm();
+
+ bta_sys_policy_register((tBTA_SYS_CONN_CBACK*)bta_dm_policy_cback);
+
+
+ // BLUEDROID REMOVE ??
+#if 0
+#if 1
+ /* Create broadcom primary DI record */
+ if(WBT_ExtCreateRecord())
+ {
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )
+ /* while app_ready_timer is running, BTA DM doesn't send EIR to controller */
+ bta_dm_cb.app_ready_timer.p_cback = (TIMER_CBACK*)&bta_dm_app_ready_timer_cback;
+ bta_sys_start_timer(&bta_dm_cb.app_ready_timer, 0, 100);
+
+ bta_sys_add_uuid(UUID_SERVCLASS_PNP_INFORMATION);
+#endif
+ bta_dm_di_cb.di_handle[bta_dm_di_cb.di_num] = 0; /* primary DI record */
+ bta_dm_di_cb.di_num ++;
+ }
+#else /* Eventually implement pin code */
+ if (WBT_ExtCreateRecord())
+ WBT_ExtAddPinCode();
+#endif
+#endif
+ }
+ else
+ APPL_TRACE_DEBUG0(" --- ignored event");
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_disable
+**
+** Description Disables the BT device manager
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_disable (tBTA_DM_MSG *p_data)
+{
+ /* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after last channel is closed) */
+ L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0);
+
+ /* disable all active subsystems */
+ bta_sys_disable(BTA_SYS_HW_BLUETOOTH);
+
+ BTM_SetDiscoverability(BTM_NON_DISCOVERABLE, 0, 0);
+ BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0);
+
+ bta_dm_disable_pm();
+
+ bta_dm_cb.disabling = TRUE;
+
+ bta_dm_search_cancel(NULL);
+
+ if(BTM_GetNumAclLinks()==0)
+ {
+#if (defined(BTA_DISABLE_DELAY) && BTA_DISABLE_DELAY > 0)
+ /* If BTA_DISABLE_DELAY is defined and greater than zero, then delay the shutdown by
+ * BTA_DISABLE_DELAY milliseconds
+ */
+ APPL_TRACE_WARNING2("%s BTA_DISABLE_DELAY set to %d ms",
+ __FUNCTION__, BTA_DISABLE_DELAY);
+ bta_sys_stop_timer(&bta_dm_cb.disable_timer);
+ bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_conn_down_timer_cback;
+ bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, BTA_DISABLE_DELAY);
+#else
+ bta_dm_disable_conn_down_timer_cback(NULL);
+#endif
+ }
+ else
+ {
+ bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
+ bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 5000);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_disable_timer_cback
+**
+** Description Called if the disable timer expires
+** Used to close ACL connections which are still active
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_disable_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+
+ UINT8 i;
+
+ APPL_TRACE_EVENT0(" bta_dm_disable_timer_cback ");
+
+ if(BTM_GetNumAclLinks())
+ {
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ btm_remove_acl(bta_dm_cb.device_list.peer_device[i].peer_bdaddr);
+
+ }
+
+ }
+ else
+ {
+ bta_dm_cb.disabling = FALSE;
+
+ bta_sys_remove_uuid(UUID_SERVCLASS_PNP_INFORMATION);
+ bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL);
+ }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_dm_set_dev_name
+**
+** Description Sets local device name
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_set_dev_name (tBTA_DM_MSG *p_data)
+{
+
+ BTM_SetLocalDeviceName((char*)p_data->set_name.name);
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+ bta_dm_set_eir ((char*)p_data->set_name.name);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_set_visibility
+**
+** Description Sets discoverability, connectability and pairability
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_set_visibility (tBTA_DM_MSG *p_data)
+{
+
+
+ /* set modes for Discoverability and connectability if not ignore */
+ if (p_data->set_visibility.disc_mode != BTA_DM_IGNORE)
+ BTM_SetDiscoverability((UINT8)p_data->set_visibility.disc_mode,
+ bta_dm_cb.inquiry_scan_window,
+ bta_dm_cb.inquiry_scan_interval);
+
+ if (p_data->set_visibility.conn_mode != BTA_DM_IGNORE)
+ BTM_SetConnectability((UINT8)p_data->set_visibility.conn_mode,
+ bta_dm_cb.page_scan_window,
+ bta_dm_cb.page_scan_interval);
+
+ /* Send False or True if not ignore */
+ if (p_data->set_visibility.pair_mode != BTA_DM_IGNORE )
+ {
+
+ if (p_data->set_visibility.pair_mode == BTA_DM_NON_PAIRABLE)
+ bta_dm_cb.disable_pair_mode = TRUE;
+ else
+ bta_dm_cb.disable_pair_mode = FALSE;
+
+ }
+
+ /* Send False or True if not ignore */
+ if (p_data->set_visibility.conn_paired_only != BTA_DM_IGNORE)
+ {
+
+ if (p_data->set_visibility.conn_paired_only == BTA_DM_CONN_ALL)
+ bta_dm_cb.conn_paired_only = FALSE;
+ else
+ bta_dm_cb.conn_paired_only = TRUE;
+
+ }
+
+ /* Change mode if either mode is not ignore */
+ if (p_data->set_visibility.pair_mode != BTA_DM_IGNORE || p_data->set_visibility.conn_paired_only != BTA_DM_IGNORE)
+ BTM_SetPairableMode((BOOLEAN)(!(bta_dm_cb.disable_pair_mode)),bta_dm_cb.conn_paired_only);
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_set_afhchannels
+**
+** Description This function sets the AFH first and
+** last disable channel, so channels within
+** that range are disabled.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_set_afhchannels (tBTA_DM_MSG *p_data)
+{
+ BTM_SetAfhChannels(p_data->set_afhchannels.first,p_data->set_afhchannels.last);
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_vendor_spec_command
+**
+** Description Send a vendor specific command to the controller
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_vendor_spec_command (tBTA_DM_MSG *p_data)
+{
+ tBTM_STATUS status;
+
+ status = BTM_VendorSpecificCommand(p_data->vendor_command.opcode,p_data->vendor_command.param_len,p_data->vendor_command.p_param_buf, p_data->vendor_command.p_cback);
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_tx_inqpower
+**
+** Description write inquiry tx power.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_tx_inqpower(tBTA_DM_MSG *p_data)
+{
+ if (BTM_WriteInquiryTxPower (p_data->tx_inq_pwr.tx_power) == BTM_ILLEGAL_VALUE)
+ {
+ APPL_TRACE_ERROR1("Invalid Inquiry Tx Power: %d", p_data->tx_inq_pwr.tx_power);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_remove_device
+**
+** Description Removes device, Disconnects ACL link if required.
+****
+*******************************************************************************/
+void bta_dm_remove_device (tBTA_DM_MSG *p_data)
+{
+ tBTA_DM_API_REMOVE_DEVICE *p_dev = &p_data->remove_dev;
+ int i;
+ tBTA_DM_SEC sec_event;
+
+ if (BTM_IsAclConnectionUp(p_dev->bd_addr))
+ {
+ /* Take the link down first, and mark the device for removal when disconnected */
+ btm_remove_acl( p_dev->bd_addr) ;
+
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_dev->bd_addr))
+ break;
+ }
+
+ if(i < bta_dm_cb.device_list.count)
+ {
+ bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
+ }
+ }
+ else /* Ok to remove the device in application layer */
+ {
+ BTM_SecDeleteDevice(p_dev->bd_addr);
+ if( bta_dm_cb.p_sec_cback )
+ {
+ bdcpy(sec_event.link_down.bd_addr, p_dev->bd_addr);
+ /* No connection, set status to success (acl disc code not valid) */
+ sec_event.link_down.status = HCI_SUCCESS;
+ bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &sec_event);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_add_device
+**
+** Description This function adds a Link Key to an security database entry.
+** It is normally called during host startup to restore all required information
+** stored in the NVRAM.
+****
+*******************************************************************************/
+void bta_dm_add_device (tBTA_DM_MSG *p_data)
+{
+ tBTA_DM_API_ADD_DEVICE *p_dev = &p_data->add_dev;
+ UINT8 *p_dc = NULL;
+ UINT8 *p_lc = NULL;
+ UINT32 trusted_services_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
+ UINT8 index = 0;
+ UINT8 btm_mask_index = 0;
+
+ memset (trusted_services_mask, 0, sizeof(trusted_services_mask));
+
+ /* If not all zeros, the device class has been specified */
+ if (p_dev->dc_known)
+ p_dc = (UINT8 *)p_dev->dc;
+
+ if (p_dev->link_key_known)
+ p_lc = (UINT8 *)p_dev->link_key;
+
+ if (p_dev->is_trusted)
+ {
+ /* covert BTA service mask to BTM mask */
+ while (p_dev->tm && (index < BTA_MAX_SERVICE_ID))
+ {
+ if (p_dev->tm & (UINT32)(1<<index))
+ {
+
+ btm_mask_index = bta_service_id_to_btm_srv_id_lkup_tbl[index] / BTM_SEC_ARRAY_BITS;
+ trusted_services_mask[btm_mask_index] |= (UINT32)(1 << (bta_service_id_to_btm_srv_id_lkup_tbl[index] - (UINT32)(btm_mask_index * 32)));
+
+ p_dev->tm &= (UINT32)(~(1<<index));
+
+ }
+ index++;
+ }
+ }
+
+ if (!BTM_SecAddDevice (p_dev->bd_addr, p_dc, p_dev->bd_name, p_dev->features,
+ trusted_services_mask, p_lc, p_dev->key_type, p_dev->io_cap))
+ {
+ APPL_TRACE_ERROR2 ("BTA_DM: Error adding device %08x%04x",
+ (p_dev->bd_addr[0]<<24)+(p_dev->bd_addr[1]<<16)+(p_dev->bd_addr[2]<<8)+p_dev->bd_addr[3],
+ (p_dev->bd_addr[4]<<8)+p_dev->bd_addr[5]);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_bond
+**
+** Description Bonds with peer device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_bond (tBTA_DM_MSG *p_data)
+{
+ tBTM_STATUS status;
+ tBTA_DM_SEC sec_event;
+ char *p_name;
+
+ status = BTM_SecBond ( p_data->bond.bd_addr, 0, NULL, 0 );
+
+ if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED))
+ {
+
+ p_name = BTM_SecReadDevName(p_data->bond.bd_addr);
+ if (!p_name)
+ p_name = "";
+
+ memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+ bdcpy(sec_event.auth_cmpl.bd_addr, p_data->bond.bd_addr);
+ memcpy(sec_event.auth_cmpl.bd_name, p_name, (BD_NAME_LEN-1));
+ sec_event.auth_cmpl.bd_name[BD_NAME_LEN-1] = 0;
+
+/* taken care of by memset [above]
+ sec_event.auth_cmpl.key_present = FALSE;
+ sec_event.auth_cmpl.success = FALSE;
+*/
+ sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND;
+ if (status == BTM_SUCCESS)
+ sec_event.auth_cmpl.success = TRUE;
+
+ bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_bond_cancel
+**
+** Description Cancels bonding with a peer device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_bond_cancel (tBTA_DM_MSG *p_data)
+{
+ tBTM_STATUS status;
+ tBTA_DM_SEC sec_event;
+
+ APPL_TRACE_EVENT0(" bta_dm_bond_cancel ");
+ status = BTM_SecBondCancel ( p_data->bond_cancel.bd_addr );
+
+ if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED && status != BTM_SUCCESS))
+ {
+ sec_event.bond_cancel_cmpl.result = BTA_FAILURE;
+
+ bta_dm_cb.p_sec_cback(BTA_DM_BOND_CANCEL_CMPL_EVT, &sec_event);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_pin_reply
+**
+** Description Send the pin_reply to a request from BTM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_pin_reply (tBTA_DM_MSG *p_data)
+{
+ UINT32 trusted_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
+ UINT32 * current_trusted_mask;
+
+ current_trusted_mask = BTM_ReadTrustedMask(p_data->pin_reply.bd_addr);
+
+ if(current_trusted_mask)
+ {
+ memcpy(trusted_mask, current_trusted_mask, sizeof(trusted_mask));
+ }
+ else
+ {
+ memset(trusted_mask, 0, sizeof(trusted_mask));
+ }
+
+ if(p_data->pin_reply.accept)
+ {
+
+ BTM_PINCodeReply(p_data->pin_reply.bd_addr, BTM_SUCCESS, p_data->pin_reply.pin_len, p_data->pin_reply.p_pin, trusted_mask );
+ }
+ else
+ {
+ BTM_PINCodeReply(p_data->pin_reply.bd_addr, BTM_NOT_AUTHORIZED, 0, NULL, trusted_mask );
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_link_policy
+**
+** Description remove/set link policy mask.
+** wake the link, is sniff/park is removed
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_link_policy (tBTA_DM_MSG *p_data)
+{
+ tBTA_DM_PEER_DEVICE *p_dev;
+
+ p_dev = bta_dm_find_peer_device(p_data->link_policy.bd_addr);
+ if(!p_dev)
+ return;
+
+ APPL_TRACE_DEBUG2(" bta_dm_link_policy set:%d, policy:0x%x",
+ p_data->link_policy.set, p_data->link_policy.policy_mask);
+ if(p_data->link_policy.set)
+ {
+ /* restore the default link policy */
+ p_dev->link_policy |= p_data->link_policy.policy_mask;
+ BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+ }
+ else
+ {
+ /* clear the policy from the default link policy */
+ p_dev->link_policy &= (~p_data->link_policy.policy_mask);
+ BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+
+ if(p_data->link_policy.policy_mask & (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE))
+ {
+ /* if clearing sniff/park, wake the link */
+ bta_dm_pm_active(p_dev->peer_bdaddr);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_policy_cback
+**
+** Description process the link policy changes
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ tBTA_DM_PEER_DEVICE *p_dev = NULL;
+ UINT16 policy = app_id;
+ UINT32 mask = (UINT32)(1 << id);
+
+ if(peer_addr)
+ p_dev = bta_dm_find_peer_device(peer_addr);
+
+ APPL_TRACE_DEBUG2(" bta_dm_policy_cback cmd:%d, policy:0x%x",
+ status, policy);
+ switch(status)
+ {
+ case BTA_SYS_PLCY_SET:
+ if(!p_dev)
+ return;
+ /* restore the default link policy */
+ p_dev->link_policy |= policy;
+ BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+ break;
+
+ case BTA_SYS_PLCY_CLR:
+ if(!p_dev)
+ return;
+ /* clear the policy from the default link policy */
+ p_dev->link_policy &= (~policy);
+ BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+
+ if(policy & (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE))
+ {
+ /* if clearing sniff/park, wake the link */
+ bta_dm_pm_active(p_dev->peer_bdaddr);
+ }
+ break;
+
+ case BTA_SYS_PLCY_DEF_SET:
+ /* want to restore/set the role switch policy */
+ bta_dm_cb.role_policy_mask &= ~mask;
+ if(0 == bta_dm_cb.role_policy_mask)
+ {
+ /* if nobody wants to insist on the role */
+ bta_dm_cb.cur_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+ }
+ break;
+
+ case BTA_SYS_PLCY_DEF_CLR:
+ /* want to remove the role switch policy */
+ bta_dm_cb.role_policy_mask |= mask;
+ bta_dm_cb.cur_policy &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;
+ BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+ break;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_auth_reply
+**
+** Description Send the authorization reply to a request from BTM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_auth_reply (tBTA_DM_MSG *p_data)
+{
+
+ UINT32 trusted_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
+ UINT8 btm_mask_index = 0;
+ UINT32 * current_trusted_mask;
+
+ current_trusted_mask = BTM_ReadTrustedMask(p_data->auth_reply.bd_addr);
+
+ if(current_trusted_mask)
+ {
+ memcpy(trusted_mask, current_trusted_mask, sizeof(trusted_mask));
+ }
+ else
+ {
+ memset(trusted_mask, 0, sizeof(trusted_mask));
+ }
+
+ if(p_data->auth_reply.response != BTA_DM_NOT_AUTH)
+ {
+ if(p_data->auth_reply.response == BTA_DM_AUTH_PERM)
+ {
+ if(p_data->auth_reply.service < BTA_MAX_SERVICE_ID)
+ {
+ /* convert BTA service id to BTM mask */
+ btm_mask_index = bta_service_id_to_btm_srv_id_lkup_tbl[p_data->auth_reply.service] / 32;
+ trusted_mask[btm_mask_index] |= (UINT32)(1 << (bta_service_id_to_btm_srv_id_lkup_tbl[p_data->auth_reply.service] - (UINT32)(btm_mask_index * 32)));
+
+ }
+ }
+ BTM_DeviceAuthorized (p_data->auth_reply.bd_addr, BTM_SUCCESS,trusted_mask);
+ }
+ else
+ {
+ BTM_DeviceAuthorized (p_data->auth_reply.bd_addr, BTM_NOT_AUTHORIZED,trusted_mask);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_confirm
+**
+** Description Send the user confirm request reply in response to a
+** request from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_confirm(tBTA_DM_MSG *p_data)
+{
+ tBTM_STATUS res = BTM_NOT_AUTHORIZED;
+
+ if(p_data->confirm.accept == TRUE)
+ res = BTM_SUCCESS;
+ BTM_ConfirmReqReply(res, p_data->confirm.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_passkey_cancel
+**
+** Description Send the passkey cancel from SP initiator by sending a negative
+** passkey request replyreply.
+** Returns void
+**
+*******************************************************************************/
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+void bta_dm_passkey_cancel(tBTA_DM_MSG *p_data)
+{
+ BTM_PasskeyReqReply(BTM_NOT_AUTHORIZED, p_data->passkey_cancel.bd_addr, 0);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_dm_loc_oob
+**
+** Description Retrieve the OOB data from the local LM
+**
+** Returns void
+**
+*******************************************************************************/
+#if (BTM_OOB_INCLUDED == TRUE)
+void bta_dm_loc_oob(tBTA_DM_MSG *p_data)
+{
+ BTM_ReadLocalOobData();
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_ci_io_req_act
+**
+** Description respond to the IO capabilities request from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data)
+{
+ tBTM_AUTH_REQ auth_req = BTM_AUTH_AP_NO;
+ if(p_data->ci_io_req.auth_req)
+ auth_req = BTM_AUTH_AP_YES;
+ BTM_IoCapRsp(p_data->ci_io_req.bd_addr, p_data->ci_io_req.io_cap,
+ p_data->ci_io_req.oob_data, auth_req);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_ci_rmt_oob_act
+**
+** Description respond to the OOB data request for the remote device from BTM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data)
+{
+ tBTM_STATUS res = BTM_NOT_AUTHORIZED;
+
+ if(p_data->ci_rmt_oob.accept == TRUE)
+ res = BTM_SUCCESS;
+ BTM_RemoteOobDataReply(res, p_data->ci_rmt_oob.bd_addr,
+ p_data->ci_rmt_oob.c, p_data->ci_rmt_oob.r );
+}
+#endif /* BTM_OOB_INCLUDED */
+
+/*******************************************************************************
+**
+** Function bta_dm_search_start
+**
+** Description Starts an inquiry
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_start (tBTA_DM_MSG *p_data)
+{
+ tBTM_INQUIRY_CMPL result;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->search.num_uuid);
+#endif
+
+ APPL_TRACE_DEBUG1("bta_dm_search_start avoid_scatter=%d", bta_dm_cfg.avoid_scatter);
+ if (bta_dm_cfg.avoid_scatter &&
+ (p_data->search.rs_res == BTA_DM_RS_NONE) && bta_dm_check_av(BTA_DM_API_SEARCH_EVT))
+ {
+ memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH));
+ return;
+ }
+
+ BTM_ClearInqDb(NULL);
+ /* save search params */
+ bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
+ bta_dm_search_cb.services = p_data->search.services;
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+ utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+
+ if ((bta_dm_search_cb.num_uuid = p_data->search.num_uuid) != 0 &&
+ p_data->search.p_uuid != NULL)
+ {
+ if ((bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len)) == NULL)
+ {
+ APPL_TRACE_ERROR0("bta_dm_search_start no resources");
+
+ result.status = BTA_FAILURE;
+ result.num_resp = 0;
+ bta_dm_inq_cmpl_cb ((void *)&result);
+ return;
+ }
+// bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len);
+ memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len);
+ }
+
+ if (p_data->search.inq_params.mode & BTM_LIMITED_INQUIRY)
+ p_data->search.inq_params.mode |= BTM_BLE_LIMITED_INQUIRY;
+ else
+ p_data->search.inq_params.mode |= BTM_BLE_GENERAL_INQUIRY;
+#endif
+ result.status = BTM_StartInquiry( (tBTM_INQ_PARMS*)&p_data->search.inq_params,
+ bta_dm_inq_results_cb,
+ (tBTM_CMPL_CB*) bta_dm_inq_cmpl_cb);
+
+ APPL_TRACE_EVENT1("bta_dm_search_start status=%d", result.status);
+ if (result.status != BTM_CMD_STARTED)
+ {
+ result.num_resp = 0;
+ bta_dm_inq_cmpl_cb ((void *)&result);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_search_cancel
+**
+** Description Cancels an ongoing search for devices
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_cancel (tBTA_DM_MSG *p_data)
+{
+
+ tBTA_DM_MSG * p_msg;
+
+ if(BTM_IsInquiryActive())
+ {
+ BTM_CancelInquiry();
+ bta_dm_search_cancel_notify(NULL);
+
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+ p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+ bta_sys_sendmsg(p_msg);
+
+ }
+ }
+ /* If no Service Search going on then issue cancel remote name in case it is active */
+ else if (!bta_dm_search_cb.name_discover_done)
+ {
+ BTM_CancelRemoteDeviceName();
+ }
+#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+ if (bta_dm_search_cb.gatt_disc_active)
+ {
+ bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_discover
+**
+** Description Discovers services on a remote device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_discover (tBTA_DM_MSG *p_data)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->discover.num_uuid);
+#endif
+ APPL_TRACE_EVENT2("bta_dm_discover services_to_search=0x%04X, sdp_search=%d",
+ p_data->discover.services, p_data->discover.sdp_search);
+
+ /* save the search condition */
+ bta_dm_search_cb.services = p_data->discover.services;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+ if ((bta_dm_search_cb.num_uuid = p_data->discover.num_uuid) != 0 &&
+ p_data->discover.p_uuid != NULL)
+ {
+ if ((bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len)) == NULL)
+ {
+ p_data->discover.p_cback(BTA_DM_DISC_CMPL_EVT, NULL);
+ return;
+ }
+ memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->discover.p_uuid, len);
+ }
+ bta_dm_search_cb.uuid_to_search = bta_dm_search_cb.num_uuid;
+#endif
+
+ bta_dm_search_cb.p_search_cback = p_data->discover.p_cback;
+ bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
+ bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;
+ bta_dm_search_cb.service_index = 0;
+ bta_dm_search_cb.services_found = 0;
+ bta_dm_search_cb.peer_name[0] = 0;
+ bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
+ bta_dm_search_cb.p_btm_inq_info = BTM_InqDbRead (p_data->discover.bd_addr);
+
+ bta_dm_search_cb.name_discover_done = FALSE;
+ memcpy(&bta_dm_search_cb.uuid, &p_data->discover.uuid, sizeof(tSDP_UUID));
+ bta_dm_discover_device(p_data->discover.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_di_disc_cmpl
+**
+** Description Sends event to application when DI discovery complete
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_di_disc_cmpl(tBTA_DM_MSG *p_data)
+{
+ tBTA_DM_DI_DISC_CMPL di_disc;
+
+ memset(&di_disc, 0, sizeof(tBTA_DM_DI_DISC_CMPL));
+ bdcpy(di_disc.bd_addr, bta_dm_search_cb.peer_bdaddr);
+
+ if((p_data->hdr.offset == SDP_SUCCESS)
+ || (p_data->hdr.offset == SDP_DB_FULL))
+ {
+ di_disc.num_record = SDP_GetNumDiRecords(bta_dm_di_cb.p_di_db);
+ }
+ else
+ di_disc.result = BTA_FAILURE;
+
+ bta_dm_di_cb.p_di_db = NULL;
+ bta_dm_search_cb.p_search_cback(BTA_DM_DI_DISC_CMPL_EVT, (tBTA_DM_SEARCH *) &di_disc);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_di_disc_callback
+**
+** Description This function queries a remote device for DI information.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_di_disc_callback(UINT16 result)
+{
+ tBTA_DM_MSG * p_msg;
+
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+ p_msg->hdr.layer_specific = BTA_DM_API_DI_DISCOVER_EVT;
+ p_msg->hdr.offset = result;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_di_disc
+**
+** Description This function queries a remote device for DI information.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_di_disc (tBTA_DM_MSG *p_data)
+{
+ UINT16 result = BTA_FAILURE;
+ tBTA_DM_MSG *p_msg;
+
+ bta_dm_search_cb.p_search_cback = p_data->di_disc.p_cback;
+ bdcpy(bta_dm_search_cb.peer_bdaddr, p_data->di_disc.bd_addr);
+ bta_dm_di_cb.p_di_db = p_data->di_disc.p_sdp_db;
+
+ if((bta_dm_search_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_DM_SDP_DB_SIZE)) != NULL)
+ {
+ if ( SDP_DiDiscover(bta_dm_search_cb.peer_bdaddr, p_data->di_disc.p_sdp_db,
+ p_data->di_disc.len, bta_dm_di_disc_callback) == SDP_SUCCESS)
+ {
+ result = BTA_SUCCESS;
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("No buffer to start DI discovery");
+ }
+
+ if ( result == BTA_FAILURE &&
+ (p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+ p_msg->hdr.layer_specific = BTA_DM_API_DI_DISCOVER_EVT;
+ p_data->hdr.offset = result;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_read_remote_device_name
+**
+** Description Initiate to get remote device name
+**
+** Returns TRUE if started to get remote name
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr)
+{
+ tBTM_STATUS btm_status;
+
+ APPL_TRACE_DEBUG0("bta_dm_read_remote_device_name");
+
+ bdcpy(bta_dm_search_cb.peer_bdaddr, bd_addr);
+ bta_dm_search_cb.peer_name[0] = 0;
+
+ btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
+ (tBTM_CMPL_CB *) bta_dm_remname_cback);
+
+ if ( btm_status == BTM_CMD_STARTED )
+ {
+ APPL_TRACE_DEBUG0("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName is started");
+
+ return (TRUE);
+ }
+ else if ( btm_status == BTM_BUSY )
+ {
+ APPL_TRACE_DEBUG0("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName is busy");
+
+ /* Remote name discovery is on going now so BTM cannot notify through "bta_dm_remname_cback" */
+ /* adding callback to get notified that current reading remore name done */
+ BTM_SecAddRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+ return (TRUE);
+ }
+ else
+ {
+ APPL_TRACE_WARNING1("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName returns 0x%02X", btm_status);
+
+ return (FALSE);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_inq_cmpl
+**
+** Description Process the inquiry complete event from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_inq_cmpl (tBTA_DM_MSG *p_data)
+{
+ tBTA_DM_MSG * p_msg;
+ tBTA_DM_SEARCH data;
+
+ APPL_TRACE_DEBUG0("bta_dm_inq_cmpl");
+
+ data.inq_cmpl.num_resps = p_data->inq_cmpl.num;
+ bta_dm_search_cb.p_search_cback(BTA_DM_INQ_CMPL_EVT, &data);
+
+ if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbFirst()) != NULL)
+ {
+ /* start name and service discovery from the first device on inquiry result */
+ bta_dm_search_cb.name_discover_done = FALSE;
+ bta_dm_search_cb.peer_name[0] = 0;
+ bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);
+ }
+ else
+ {
+ /* no devices, search complete */
+ bta_dm_search_cb.services = 0;
+
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+ p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+ }
+
+/*******************************************************************************
+**
+** Function bta_dm_rmt_name
+**
+** Description Process the remote name result from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_rmt_name (tBTA_DM_MSG *p_data)
+{
+ APPL_TRACE_DEBUG0("bta_dm_rmt_name");
+
+ if( p_data->rem_name.result.disc_res.bd_name[0] && bta_dm_search_cb.p_btm_inq_info)
+ {
+ bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name = TRUE;
+ }
+
+ bta_dm_discover_device(bta_dm_search_cb.peer_bdaddr);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_disc_rmt_name
+**
+** Description Process the remote name result from BTM when application
+** wants to find the name for a bdaddr
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data)
+{
+ tBTM_INQ_INFO *p_btm_inq_info;
+
+ APPL_TRACE_DEBUG0("bta_dm_disc_rmt_name");
+
+ p_btm_inq_info = BTM_InqDbRead (p_data->rem_name.result.disc_res.bd_addr);
+ if( p_btm_inq_info )
+ {
+ if( p_data->rem_name.result.disc_res.bd_name[0] )
+ {
+ p_btm_inq_info->appl_knows_rem_name = TRUE;
+ }
+ }
+
+ bta_dm_discover_device(p_data->rem_name.result.disc_res.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_sdp_result
+**
+** Description Process the discovery result from sdp
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
+{
+
+ tSDP_DISC_REC *p_sdp_rec = NULL;
+ tBTA_DM_MSG *p_msg;
+ BOOLEAN service_found = FALSE;
+ BOOLEAN scn_found = FALSE;
+ UINT16 service = 0xFFFF;
+ tSDP_PROTOCOL_ELEM pe;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ tBT_UUID *p_uuid = bta_dm_search_cb.p_srvc_uuid;
+ tBTA_DM_SEARCH result;
+ tBT_UUID service_uuid;
+#endif
+
+ UINT32 num_uuids = 0;
+ UINT8 uuid_list[32][MAX_UUID_SIZE]; // assuming a max of 32 services
+
+ if((p_data->sdp_event.sdp_result == SDP_SUCCESS)
+ || (p_data->sdp_event.sdp_result == SDP_NO_RECS_MATCH)
+ || (p_data->sdp_event.sdp_result == SDP_DB_FULL))
+ {
+ APPL_TRACE_DEBUG1("sdp_result::0x%x", p_data->sdp_event.sdp_result);
+ do
+ {
+
+ service_found = FALSE;
+ p_sdp_rec = NULL;
+ if( bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID+1) )
+ {
+ p_sdp_rec = SDP_FindServiceUUIDInDb(bta_dm_search_cb.p_sdp_db, &bta_dm_search_cb.uuid, p_sdp_rec);
+
+ if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ bta_dm_search_cb.peer_scn = (UINT8) pe.params[0];
+ scn_found = TRUE;
+ }
+ }
+ else
+ {
+ service = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index-1];
+ p_sdp_rec = SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db, service, p_sdp_rec);
+ }
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ /* finished with BR/EDR services, now we check the result for GATT based service UUID */
+ if (bta_dm_search_cb.service_index == BTA_MAX_SERVICE_ID)
+ {
+ if (bta_dm_search_cb.uuid_to_search != 0 && p_uuid != NULL)
+ {
+ p_uuid += (bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search);
+ /* only support 16 bits UUID for now */
+ service = p_uuid->uu.uuid16;
+
+ }
+ /* all GATT based services */
+ do
+ {
+ /* find a service record, report it */
+ p_sdp_rec = SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db,
+ 0, p_sdp_rec);
+ if (p_sdp_rec)
+ {
+ if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
+ {
+ /* send result back to app now, one by one */
+ bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+ result.disc_ble_res.service.len = service_uuid.len;
+ result.disc_ble_res.service.uu.uuid16 = service_uuid.uu.uuid16;
+
+ bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
+ }
+ }
+
+ if (bta_dm_search_cb.uuid_to_search > 0)
+ break;
+
+ } while (p_sdp_rec);
+ }
+ else
+#endif
+ {
+ /* SDP_DB_FULL means some records with the
+ required attributes were received */
+ if(((p_data->sdp_event.sdp_result == SDP_DB_FULL) &&
+ bta_dm_search_cb.services != BTA_ALL_SERVICE_MASK) ||
+ (p_sdp_rec != NULL))
+ {
+ /* If Plug and Play service record, check to see if Broadcom stack */
+ if (service == UUID_SERVCLASS_PNP_INFORMATION)
+ {
+ if (p_sdp_rec)
+ {
+ if (SDP_FindAttributeInRec (p_sdp_rec, ATTR_ID_EXT_BRCM_VERSION))
+ {
+ service_found = TRUE;
+ }
+ }
+ }
+ else
+ {
+ service_found = TRUE;
+ }
+
+ if (service_found)
+ {
+ UINT16 tmp_svc = 0xFFFF;
+ bta_dm_search_cb.services_found |=
+ (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index-1));
+ tmp_svc = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index-1];
+ /* Add to the list of UUIDs */
+ sdpu_uuid16_to_uuid128(tmp_svc, uuid_list[num_uuids]);
+ num_uuids++;
+ }
+ }
+ }
+
+ if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK &&
+ bta_dm_search_cb.services_to_search == 0)
+ {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ if ( bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID &&
+ bta_dm_search_cb.uuid_to_search > 0)
+ bta_dm_search_cb.uuid_to_search --;
+
+ if (bta_dm_search_cb.uuid_to_search == 0 ||
+ bta_dm_search_cb.service_index != BTA_BLE_SERVICE_ID)
+#endif
+ bta_dm_search_cb.service_index++;
+ }
+ else /* regular one service per search or PNP search */
+ break;
+
+ }
+ while(bta_dm_search_cb.service_index <= BTA_MAX_SERVICE_ID);
+
+// GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+// bta_dm_search_cb.p_sdp_db = NULL;
+ APPL_TRACE_DEBUG1("bta_dm_sdp_result services_found = %04x", bta_dm_search_cb.services_found);
+
+ /* Collect the 128-bit services here and put them into the list */
+ if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK)
+ {
+ p_sdp_rec = NULL;
+ do
+ {
+ tBT_UUID temp_uuid;
+ /* find a service record, report it */
+ p_sdp_rec = SDP_FindServiceInDb_128bit(bta_dm_search_cb.p_sdp_db, p_sdp_rec);
+ if (p_sdp_rec)
+ {
+ if (SDP_FindServiceUUIDInRec_128bit(p_sdp_rec, &temp_uuid))
+ {
+ memcpy(uuid_list[num_uuids], temp_uuid.uu.uuid128, MAX_UUID_SIZE);
+ num_uuids++;
+ }
+ }
+ } while (p_sdp_rec);
+ }
+ /* if there are more services to search for */
+ if(bta_dm_search_cb.services_to_search)
+ {
+ /* Free up the p_sdp_db before checking the next one */
+ bta_dm_free_sdp_db(NULL);
+ bta_dm_find_services(bta_dm_search_cb.peer_bdaddr);
+ }
+ else
+ {
+ /* callbacks */
+ /* start next bd_addr if necessary */
+
+ BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+ p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
+ p_msg->disc_result.result.disc_res.p_raw_data = NULL;
+ p_msg->disc_result.result.disc_res.raw_data_size = 0;
+ p_msg->disc_result.result.disc_res.num_uuids = num_uuids;
+ p_msg->disc_result.result.disc_res.p_uuid_list = NULL;
+ if (num_uuids > 0) {
+ p_msg->disc_result.result.disc_res.p_uuid_list = (UINT8*)GKI_getbuf(num_uuids*MAX_UUID_SIZE);
+ if (p_msg->disc_result.result.disc_res.p_uuid_list) {
+ memcpy(p_msg->disc_result.result.disc_res.p_uuid_list, uuid_list,
+ num_uuids*MAX_UUID_SIZE);
+ } else {
+ p_msg->disc_result.result.disc_res.num_uuids = 0;
+ APPL_TRACE_ERROR1("%s: Unable to allocate memory for uuid_list", __FUNCTION__);
+ }
+ }
+ //copy the raw_data to the discovery result structure
+ //
+ APPL_TRACE_DEBUG2("bta_dm_sdp_result (raw_data used = 0x%x raw_data_ptr = 0x%x)\r\n",bta_dm_search_cb.p_sdp_db->raw_used, bta_dm_search_cb.p_sdp_db->raw_data);
+
+ if ( bta_dm_search_cb.p_sdp_db != NULL && bta_dm_search_cb.p_sdp_db->raw_used != 0 &&
+ bta_dm_search_cb.p_sdp_db->raw_data != NULL) {
+
+ p_msg->disc_result.result.disc_res.p_raw_data = GKI_getbuf(bta_dm_search_cb.p_sdp_db->raw_used);
+ if ( NULL != p_msg->disc_result.result.disc_res.p_raw_data ) {
+ memcpy( p_msg->disc_result.result.disc_res.p_raw_data,
+ bta_dm_search_cb.p_sdp_db->raw_data,
+ bta_dm_search_cb.p_sdp_db->raw_used );
+
+ p_msg->disc_result.result.disc_res.raw_data_size =
+ bta_dm_search_cb.p_sdp_db->raw_used;
+
+ } else {
+ APPL_TRACE_DEBUG1("bta_dm_sdp_result GKI Alloc failed to allocate %d bytes !!\r\n",bta_dm_search_cb.p_sdp_db->raw_used);
+ }
+
+ bta_dm_search_cb.p_sdp_db->raw_data = NULL; //no need to free this - it is a global assigned.
+ bta_dm_search_cb.p_sdp_db->raw_used = 0;
+ bta_dm_search_cb.p_sdp_db->raw_size = 0;
+ }
+ else {
+ APPL_TRACE_DEBUG0("bta_dm_sdp_result raw data size is 0 or raw_data is null!!\r\n");
+ }
+ /* Done with p_sdp_db. Free it */
+ bta_dm_free_sdp_db(NULL);
+ p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+
+ //Piggy back the SCN over result field
+ if( scn_found )
+ {
+ p_msg->disc_result.result.disc_res.result = (3 + bta_dm_search_cb.peer_scn);
+ p_msg->disc_result.result.disc_res.services |= BTA_USER_SERVICE_MASK;
+
+ APPL_TRACE_EVENT1(" Piggy back the SCN over result field SCN=%d", bta_dm_search_cb.peer_scn);
+
+ }
+ bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+ bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+ /* make sure the string is null terminated */
+ p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+ bta_sys_sendmsg(p_msg);
+ }
+
+ }
+
+ }
+ else
+ {
+ /* conn failed. No need for timer */
+ if(p_data->sdp_event.sdp_result == SDP_CONN_FAILED || p_data->sdp_event.sdp_result == SDP_CONN_REJECTED
+ || p_data->sdp_event.sdp_result == SDP_SECURITY_ERR)
+ bta_dm_search_cb.wait_disc = FALSE;
+
+ /* not able to connect go to next device */
+ GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+ bta_dm_search_cb.p_sdp_db = NULL;
+
+ BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+ p_msg->disc_result.result.disc_res.result = BTA_FAILURE;
+ p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+ bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+ bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+ /* make sure the string is null terminated */
+ p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_search_cmpl
+**
+** Description Sends event to application
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_cmpl (tBTA_DM_MSG *p_data)
+{
+ APPL_TRACE_DEBUG0("bta_dm_search_cmpl");
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+ utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+#endif
+
+ if (p_data->hdr.layer_specific == BTA_DM_API_DI_DISCOVER_EVT)
+ bta_dm_di_disc_cmpl(p_data);
+ else
+ bta_dm_search_cb.p_search_cback(BTA_DM_DISC_CMPL_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_disc_result
+**
+** Description Service discovery result when discovering services on a device
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_disc_result (tBTA_DM_MSG *p_data)
+{
+ tBTA_DM_MSG * p_msg;
+
+ APPL_TRACE_DEBUG0("bta_dm_disc_result");
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ /* if any BR/EDR service discovery has been done, report the event */
+ if ((bta_dm_search_cb.services & ((BTA_ALL_SERVICE_MASK | BTA_USER_SERVICE_MASK ) & ~BTA_BLE_SERVICE_MASK)))
+#endif
+ bta_dm_search_cb.p_search_cback(BTA_DM_DISC_RES_EVT, &p_data->disc_result.result);
+
+ /* send a message to change state */
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+ p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_search_result
+**
+** Description Service discovery result while searching for devices
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_result (tBTA_DM_MSG *p_data)
+{
+ APPL_TRACE_DEBUG2("bta_dm_search_result searching:0x%04x, result:0x%04x",
+ bta_dm_search_cb.services,
+ p_data->disc_result.result.disc_res.services);
+
+ /* call back if application wants name discovery or found services that application is searching */
+ if (( !bta_dm_search_cb.services )
+ ||(( bta_dm_search_cb.services ) && ( p_data->disc_result.result.disc_res.services )))
+ {
+ bta_dm_search_cb.p_search_cback(BTA_DM_DISC_RES_EVT, &p_data->disc_result.result);
+ }
+
+ /* if searching did not initiate to create link */
+ if(!bta_dm_search_cb.wait_disc )
+ {
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+ /* if service searching is done with EIR, don't search next device */
+ if( bta_dm_search_cb.p_btm_inq_info )
+#endif
+ bta_dm_discover_next_device();
+ }
+ else
+ {
+ /* wait until link is disconnected or timeout */
+ bta_dm_search_cb.sdp_results = TRUE;
+ bta_dm_search_cb.search_timer.p_cback = (TIMER_CBACK*)&bta_dm_search_timer_cback;
+ bta_sys_start_timer(&bta_dm_search_cb.search_timer, 0, 1000*(L2CAP_LINK_INACTIVITY_TOUT+1) );
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_search_timer_cback
+**
+** Description Called when ACL disconnect time is over
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_search_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+
+ APPL_TRACE_EVENT0(" bta_dm_search_timer_cback ");
+ bta_dm_search_cb.wait_disc = FALSE;
+
+ /* proceed with next device */
+ bta_dm_discover_next_device();
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_free_sdp_db
+**
+** Description Frees SDP data base
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_free_sdp_db (tBTA_DM_MSG *p_data)
+{
+ if(bta_dm_search_cb.p_sdp_db)
+ {
+ GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+ bta_dm_search_cb.p_sdp_db = NULL;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_queue_search
+**
+** Description Queues search command while search is being cancelled
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_queue_search (tBTA_DM_MSG *p_data)
+{
+
+ bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)GKI_getbuf(sizeof(tBTA_DM_API_SEARCH));
+ memcpy(bta_dm_search_cb.p_search_queue, p_data, sizeof(tBTA_DM_API_SEARCH));
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_queue_disc
+**
+** Description Queues discovery command while search is being cancelled
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_queue_disc (tBTA_DM_MSG *p_data)
+{
+
+ bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER));
+ memcpy(bta_dm_search_cb.p_search_queue, p_data, sizeof(tBTA_DM_API_DISCOVER));
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_search_clear_queue
+**
+** Description Clears the queue if API search cancel is called
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_clear_queue (tBTA_DM_MSG *p_data)
+{
+
+ if(bta_dm_search_cb.p_search_queue)
+ {
+ GKI_freebuf(bta_dm_search_cb.p_search_queue);
+ bta_dm_search_cb.p_search_queue = NULL;
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_search_cancel_cmpl
+**
+** Description Search cancel is complete
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_cmpl (tBTA_DM_MSG *p_data)
+{
+
+ if(bta_dm_search_cb.p_search_queue)
+ {
+ bta_sys_sendmsg(bta_dm_search_cb.p_search_queue);
+ bta_dm_search_cb.p_search_queue = NULL;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_search_cancel_transac_cmpl
+**
+** Description Current Service Discovery or remote name procedure is
+** completed after search cancellation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data)
+{
+
+ if(bta_dm_search_cb.p_sdp_db)
+ {
+ GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+ bta_dm_search_cb.p_sdp_db = NULL;
+ }
+
+ bta_dm_search_cancel_notify(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_search_cancel_notify
+**
+** Description Notify application that search has been cancelled
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data)
+{
+ if (bta_dm_search_cb.p_search_cback)
+ {
+ bta_dm_search_cb.p_search_cback(BTA_DM_SEARCH_CANCEL_CMPL_EVT, NULL);
+ }
+ if (!bta_dm_search_cb.name_discover_done)
+ {
+ BTM_CancelRemoteDeviceName();
+ }
+#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+ if (bta_dm_search_cb.gatt_disc_active)
+ {
+ bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+ }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_find_services
+**
+** Description Starts discovery on a device
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_find_services ( BD_ADDR bd_addr)
+{
+
+ tSDP_UUID uuid;
+ UINT16 attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, ATTR_ID_EXT_BRCM_VERSION};
+ UINT16 num_attrs = 1;
+ tBTA_DM_MSG *p_msg;
+
+ memset (&uuid, 0, sizeof(tSDP_UUID));
+
+ while(bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID)
+ {
+ if( bta_dm_search_cb.services_to_search
+ & (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)))
+ {
+ if((bta_dm_search_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_DM_SDP_DB_SIZE)) != NULL)
+ {
+ APPL_TRACE_DEBUG1("bta_dm_search_cb.services = %04x***********", bta_dm_search_cb.services);
+ /* try to search all services by search based on L2CAP UUID */
+ if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK )
+ {
+ APPL_TRACE_ERROR1("services_to_search = %08x",bta_dm_search_cb.services_to_search);
+ if (bta_dm_search_cb.services_to_search & BTA_RES_SERVICE_MASK)
+ {
+ uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[0];
+ bta_dm_search_cb.services_to_search &= ~BTA_RES_SERVICE_MASK;
+ }
+ else
+ {
+ uuid.uu.uuid16 = UUID_PROTOCOL_L2CAP;
+ bta_dm_search_cb.services_to_search = 0;
+ }
+ }
+ else
+ {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ /* for LE only profile */
+ if (bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID)
+ {
+ if (bta_dm_search_cb.uuid_to_search > 0 && bta_dm_search_cb.p_srvc_uuid)
+ {
+ memcpy(&uuid,
+ (const void *)(bta_dm_search_cb.p_srvc_uuid + \
+ bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search),
+ sizeof(tBT_UUID));
+
+ bta_dm_search_cb.uuid_to_search -- ;
+ }
+ else
+ uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index];
+
+ /* last one? clear the BLE service bit if all discovery has been done */
+ if (bta_dm_search_cb.uuid_to_search == 0)
+ bta_dm_search_cb.services_to_search &=
+ (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)));
+
+ }
+ else
+#endif
+ {
+ /* remove the service from services to be searched */
+ bta_dm_search_cb.services_to_search &=
+ (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)));
+ uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index];
+ }
+ }
+
+ if (uuid.len == 0)
+ uuid.len = LEN_UUID_16;
+
+#if 0
+ if (uuid.uu.uuid16 == UUID_SERVCLASS_PNP_INFORMATION)
+ {
+ num_attrs = 2;
+ }
+#endif
+
+ if (bta_dm_search_cb.service_index == BTA_USER_SERVICE_ID)
+ {
+ memcpy(&uuid, &bta_dm_search_cb.uuid, sizeof(tSDP_UUID));
+ }
+
+
+ APPL_TRACE_ERROR1("****************search UUID = %04x***********", uuid.uu.uuid16);
+ //SDP_InitDiscoveryDb (bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, num_attrs, attr_list);
+ SDP_InitDiscoveryDb (bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, 0, NULL);
+
+
+ memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf));
+ bta_dm_search_cb.p_sdp_db->raw_data = g_disc_raw_data_buf;
+
+ bta_dm_search_cb.p_sdp_db->raw_size = MAX_DISC_RAW_DATA_BUF;
+
+ if (!SDP_ServiceSearchAttributeRequest (bd_addr, bta_dm_search_cb.p_sdp_db, &bta_dm_sdp_callback))
+ {
+ /* if discovery not successful with this device
+ proceed to next one */
+ GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+ bta_dm_search_cb.p_sdp_db = NULL;
+ bta_dm_search_cb.service_index = BTA_MAX_SERVICE_ID;
+
+ }
+ else
+ {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ if ((bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID &&
+ bta_dm_search_cb.uuid_to_search == 0) ||
+ bta_dm_search_cb.service_index != BTA_BLE_SERVICE_ID)
+#endif
+ bta_dm_search_cb.service_index++;
+ return;
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("#### Failed to allocate SDP DB buffer! ####");
+ }
+ }
+
+ bta_dm_search_cb.service_index++;
+ }
+
+ /* no more services to be discovered */
+ if(bta_dm_search_cb.service_index >= BTA_MAX_SERVICE_ID)
+ {
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+ p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+ bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+ bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+ /* make sure the string is terminated */
+ p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_discover_next_device
+**
+** Description Starts discovery on the next device in Inquiry data base
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_discover_next_device(void)
+{
+
+ tBTA_DM_MSG * p_msg;
+
+ APPL_TRACE_DEBUG0("bta_dm_discover_next_device");
+
+ /* searching next device on inquiry result */
+ if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbNext(bta_dm_search_cb.p_btm_inq_info)) != NULL)
+ {
+ bta_dm_search_cb.name_discover_done = FALSE;
+ bta_dm_search_cb.peer_name[0] = 0;
+ bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);
+ }
+ else
+ {
+ /* no devices, search complete */
+ bta_dm_search_cb.services = 0;
+
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+ p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_discover_device
+**
+** Description Starts name and service discovery on the device
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_discover_device(BD_ADDR remote_bd_addr)
+{
+ tBTA_DM_MSG * p_msg;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type;
+#endif
+
+ APPL_TRACE_DEBUG6("bta_dm_discover_device, BDA:0x%02X%02X%02X%02X%02X%02X",
+ remote_bd_addr[0],remote_bd_addr[1],
+ remote_bd_addr[2],remote_bd_addr[3],
+ remote_bd_addr[4],remote_bd_addr[5]);
+
+ bdcpy(bta_dm_search_cb.peer_bdaddr, remote_bd_addr);
+
+ APPL_TRACE_DEBUG2("bta_dm_discover_device name_discover_done = %d p_btm_inq_info 0x%x ",
+ bta_dm_search_cb.name_discover_done,
+ bta_dm_search_cb.p_btm_inq_info
+ );
+ if ( bta_dm_search_cb.p_btm_inq_info ) {
+
+ APPL_TRACE_DEBUG1("bta_dm_discover_device appl_knows_rem_name %d",
+ bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name
+ );
+ }
+
+ /* if name discovery is not done and application needs remote name */
+ if ((!bta_dm_search_cb.name_discover_done)
+ && (( bta_dm_search_cb.p_btm_inq_info == NULL )
+ ||(bta_dm_search_cb.p_btm_inq_info && (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name))))
+ {
+ if( bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr) == TRUE )
+ {
+ return;
+ }
+ else
+ {
+ /* starting name discovery failed */
+ bta_dm_search_cb.name_discover_done = TRUE;
+ }
+ }
+
+ /* if application wants to discover service */
+ if ( bta_dm_search_cb.services )
+ {
+ /* initialize variables */
+ bta_dm_search_cb.service_index = 0;
+ bta_dm_search_cb.services_found = 0;
+ bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ bta_dm_search_cb.uuid_to_search = bta_dm_search_cb.num_uuid;
+#endif
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+ if ((bta_dm_search_cb.p_btm_inq_info != NULL) &&
+ bta_dm_search_cb.services != BTA_USER_SERVICE_MASK
+ &&(bta_dm_search_cb.sdp_search == FALSE))
+ {
+ /* check if EIR provides the information of supported services */
+ bta_dm_eir_search_services( &bta_dm_search_cb.p_btm_inq_info->results,
+ &bta_dm_search_cb.services_to_search,
+ &bta_dm_search_cb.services_found );
+ }
+
+ /* if seaching with EIR is not completed */
+ if(bta_dm_search_cb.services_to_search)
+#endif
+ {
+ /* check whether connection already exists to the device
+ if connection exists, we don't have to wait for ACL
+ link to go down to start search on next device */
+ if(BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr))
+ bta_dm_search_cb.wait_disc = FALSE;
+ else
+ bta_dm_search_cb.wait_disc = TRUE;
+
+#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+ if ( bta_dm_search_cb.p_btm_inq_info )
+ {
+ APPL_TRACE_DEBUG3("bta_dm_discover_device p_btm_inq_info 0x%x results.device_type 0x%x services_to_search 0x%x",
+ bta_dm_search_cb.p_btm_inq_info,
+ bta_dm_search_cb.p_btm_inq_info->results.device_type,
+ bta_dm_search_cb.services_to_search
+ );
+ }
+ BTM_ReadDevInfo(remote_bd_addr, &dev_type, &addr_type);
+
+ if (dev_type == BT_DEVICE_TYPE_BLE)
+ /*
+ if ( bta_dm_search_cb.p_btm_inq_info != NULL &&
+ bta_dm_search_cb.p_btm_inq_info->results.device_type == BT_DEVICE_TYPE_BLE &&
+ (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK))*/
+ {
+ if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK)
+ {
+ //set the raw data buffer here
+ memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf));
+ bta_dm_search_cb.p_ble_rawdata = g_disc_raw_data_buf;
+
+ bta_dm_search_cb.ble_raw_size = MAX_DISC_RAW_DATA_BUF;
+ bta_dm_search_cb.ble_raw_used = 0;
+
+ /* start GATT for service discovery */
+ btm_dm_start_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+ return;
+ }
+ }
+ else
+#endif
+ {
+ bta_dm_search_cb.sdp_results = FALSE;
+ bta_dm_find_services(bta_dm_search_cb.peer_bdaddr);
+
+ return;
+ }
+ }
+ }
+
+ /* name discovery and service discovery are done for this device */
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+ /* initialize the data structure - includes p_raw_data and raw_data_size */
+ memset(&(p_msg->disc_result.result), 0, sizeof(tBTA_DM_DISC_RES));
+ p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
+ p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+ bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+ (char*)bta_dm_search_cb.peer_name, (BD_NAME_LEN-1));
+
+ /* make sure the string is terminated */
+ p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_sdp_callback
+**
+** Description Callback from sdp with discovery status
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_sdp_callback (UINT16 sdp_status)
+{
+
+ tBTA_DM_SDP_RESULT * p_msg;
+
+ if ((p_msg = (tBTA_DM_SDP_RESULT *) GKI_getbuf(sizeof(tBTA_DM_SDP_RESULT))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_SDP_RESULT_EVT;
+ p_msg->sdp_result = sdp_status;
+ bta_sys_sendmsg(p_msg);
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_inq_results_cb
+**
+** Description Inquiry results callback from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir)
+{
+
+ tBTA_DM_SEARCH result;
+ tBTM_INQ_INFO *p_inq_info;
+ UINT16 service_class;
+
+ bdcpy(result.inq_res.bd_addr, p_inq->remote_bd_addr);
+ memcpy(result.inq_res.dev_class, p_inq->dev_class, DEV_CLASS_LEN);
+ BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class);
+ result.inq_res.is_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER)?TRUE:FALSE;
+ result.inq_res.rssi = p_inq->rssi;
+
+#if (BLE_INCLUDED == TRUE)
+ result.inq_res.ble_addr_type = p_inq->ble_addr_type;
+ result.inq_res.inq_result_type = p_inq->inq_result_type;
+ result.inq_res.device_type = p_inq->device_type;
+
+#endif
+
+ /* application will parse EIR to find out remote device name */
+ result.inq_res.p_eir = p_eir;
+
+ if((p_inq_info = BTM_InqDbRead(p_inq->remote_bd_addr)) != NULL)
+ {
+ /* initialize remt_name_not_required to FALSE so that we get the name by default */
+ result.inq_res.remt_name_not_required = FALSE;
+
+ }
+
+ if(bta_dm_search_cb.p_search_cback)
+ bta_dm_search_cb.p_search_cback(BTA_DM_INQ_RES_EVT, &result);
+
+ if(p_inq_info)
+ {
+ /* application indicates if it knows the remote name, inside the callback
+ copy that to the inquiry data base*/
+ if(result.inq_res.remt_name_not_required)
+ p_inq_info->appl_knows_rem_name = TRUE;
+
+ }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_inq_cmpl_cb
+**
+** Description Inquiry complete callback from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_inq_cmpl_cb (void * p_result)
+{
+
+ tBTA_DM_MSG * p_msg;
+
+ APPL_TRACE_DEBUG0("bta_dm_inq_cmpl_cb");
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->inq_cmpl.hdr.event = BTA_DM_INQUIRY_CMPL_EVT;
+ p_msg->inq_cmpl.num = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp;
+ bta_sys_sendmsg(p_msg);
+
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_service_search_remname_cback
+**
+** Description Remote name call back from BTM during service discovery
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc, BD_NAME bd_name)
+{
+ tBTM_REMOTE_DEV_NAME rem_name;
+ tBTM_STATUS btm_status;
+
+ APPL_TRACE_DEBUG1("bta_dm_service_search_remname_cback name=<%s>", bd_name);
+
+ /* if this is what we are looking for */
+ if (!bdcmp( bta_dm_search_cb.peer_bdaddr, bd_addr))
+ {
+ rem_name.length = strlen((char*)bd_name);
+ if (rem_name.length > (BD_NAME_LEN-1))
+ {
+ rem_name.length = (BD_NAME_LEN-1);
+ rem_name.remote_bd_name[(BD_NAME_LEN-1)] = 0;
+ }
+ BCM_STRNCPY_S((char*)rem_name.remote_bd_name, sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+ rem_name.status = BTM_SUCCESS;
+
+ bta_dm_remname_cback(&rem_name);
+ }
+ else
+ {
+ /* get name of device */
+ btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
+ (tBTM_CMPL_CB *) bta_dm_remname_cback);
+ if ( btm_status == BTM_BUSY )
+ {
+ /* wait for next chance(notification of remote name discovery done) */
+ APPL_TRACE_DEBUG0("bta_dm_service_search_remname_cback: BTM_ReadRemoteDeviceName is busy");
+ }
+ else if ( btm_status != BTM_CMD_STARTED )
+ {
+ /* if failed to start getting remote name then continue */
+ APPL_TRACE_WARNING1("bta_dm_service_search_remname_cback: BTM_ReadRemoteDeviceName returns 0x%02X", btm_status);
+
+ rem_name.length = 0;
+ rem_name.remote_bd_name[0] = 0;
+ rem_name.status = btm_status;
+ bta_dm_remname_cback(&rem_name);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_remname_cback
+**
+** Description Remote name complete call back from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name)
+{
+ tBTA_DM_REM_NAME * p_msg;
+
+ APPL_TRACE_DEBUG1("bta_dm_remname_cback name=<%s>", p_remote_name->remote_bd_name);
+
+ /* remote name discovery is done but it could be failed */
+ bta_dm_search_cb.name_discover_done = TRUE;
+ BCM_STRNCPY_S((char*)bta_dm_search_cb.peer_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN-1));
+ bta_dm_search_cb.peer_name[BD_NAME_LEN-1]=0;
+
+ BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+ if ((p_msg = (tBTA_DM_REM_NAME *) GKI_getbuf(sizeof(tBTA_DM_REM_NAME))) != NULL)
+ {
+ bdcpy (p_msg->result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ BCM_STRNCPY_S((char*)p_msg->result.disc_res.bd_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN-1));
+
+ /* make sure the string is null terminated */
+ p_msg->result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+ p_msg->hdr.event = BTA_DM_REMT_NAME_EVT;
+ bta_sys_sendmsg(p_msg);
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_authorize_cback
+**
+** Description cback requesting authorization
+**
+** Returns void
+**
+*******************************************************************************/
+static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
+ UINT8 *service_name, UINT8 service_id, BOOLEAN is_originator)
+{
+ tBTA_DM_SEC sec_event;
+ UINT8 index = 1;
+
+ bdcpy(sec_event.authorize.bd_addr, bd_addr);
+ memcpy(sec_event.authorize.dev_class, dev_class, DEV_CLASS_LEN);
+
+ BCM_STRNCPY_S((char*)sec_event.authorize.bd_name, sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+
+ /* make sure the string is null terminated */
+ sec_event.authorize.bd_name[BD_NAME_LEN-1] = 0;
+
+#if ( defined(BTA_JV_INCLUDED) && BTA_JV_INCLUDED == TRUE )
+ sec_event.authorize.service = service_id;
+#endif
+
+ while(index < BTA_MAX_SERVICE_ID)
+ {
+ /* get the BTA service id corresponding to BTM id */
+ if(bta_service_id_to_btm_srv_id_lkup_tbl[index] == service_id)
+ {
+ sec_event.authorize.service = index;
+ break;
+ }
+ index++;
+ }
+
+
+ /* if supported service callback otherwise not authorized */
+ if(bta_dm_cb.p_sec_cback && (index < BTA_MAX_SERVICE_ID
+#if ( defined(BTA_JV_INCLUDED) && BTA_JV_INCLUDED == TRUE )
+ /* pass through JV service ID */
+ || (service_id >= BTA_FIRST_JV_SERVICE_ID && service_id <= BTA_LAST_JV_SERVICE_ID)
+#endif
+ ))
+ {
+ bta_dm_cb.p_sec_cback(BTA_DM_AUTHORIZE_EVT, &sec_event);
+ return BTM_CMD_STARTED;
+ }
+ else
+ {
+ return BTM_NOT_AUTHORIZED;
+ }
+}
+
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_dm_pinname_cback
+**
+** Description Callback requesting pin_key
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_pinname_cback (void *p_data)
+{
+ tBTM_REMOTE_DEV_NAME *p_result = (tBTM_REMOTE_DEV_NAME *)p_data;
+ tBTA_DM_SEC sec_event;
+ UINT32 bytes_to_copy;
+ tBTA_DM_SEC_EVT event = bta_dm_cb.pin_evt;
+
+ if (BTA_DM_SP_CFM_REQ_EVT == event)
+ {
+ /* Retrieved saved device class and bd_addr */
+ bdcpy(sec_event.cfm_req.bd_addr, bta_dm_cb.pin_bd_addr);
+ BTA_COPY_DEVICE_CLASS(sec_event.cfm_req.dev_class, bta_dm_cb.pin_dev_class);
+
+ if (p_result && p_result->status == BTM_SUCCESS)
+ {
+ bytes_to_copy = (p_result->length < (BD_NAME_LEN-1))
+ ? p_result->length : (BD_NAME_LEN-1);
+ memcpy(sec_event.cfm_req.bd_name, p_result->remote_bd_name, bytes_to_copy);
+ sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+ }
+ else /* No name found */
+ sec_event.cfm_req.bd_name[0] = 0;
+
+ sec_event.key_notif.passkey = bta_dm_cb.num_val; /* get PIN code numeric number */
+
+ /* 1 additional event data fields for this event */
+ sec_event.cfm_req.just_works = bta_dm_cb.just_works;
+ }
+ else
+ {
+ /* Retrieved saved device class and bd_addr */
+ bdcpy(sec_event.pin_req.bd_addr, bta_dm_cb.pin_bd_addr);
+ BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, bta_dm_cb.pin_dev_class);
+
+ if (p_result && p_result->status == BTM_SUCCESS)
+ {
+ bytes_to_copy = (p_result->length < (BD_NAME_LEN-1))
+ ? p_result->length : (BD_NAME_LEN-1);
+ memcpy(sec_event.pin_req.bd_name, p_result->remote_bd_name, bytes_to_copy);
+ sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+ }
+ else /* No name found */
+ sec_event.pin_req.bd_name[0] = 0;
+
+ event = bta_dm_cb.pin_evt;
+ sec_event.key_notif.passkey = bta_dm_cb.num_val; /* get PIN code numeric number */
+ }
+
+ if( bta_dm_cb.p_sec_cback )
+ bta_dm_cb.p_sec_cback(event, &sec_event);
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_dm_pin_cback
+**
+** Description Callback requesting pin_key
+**
+** Returns void
+**
+*******************************************************************************/
+static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name)
+{
+ tBTA_DM_SEC sec_event;
+
+ if (!bta_dm_cb.p_sec_cback)
+ return BTM_NOT_AUTHORIZED;
+
+ /* If the device name is not known, save bdaddr and devclass and initiate a name request */
+ if (bd_name[0] == 0)
+ {
+ bta_dm_cb.pin_evt = BTA_DM_PIN_REQ_EVT;
+ bdcpy(bta_dm_cb.pin_bd_addr, bd_addr);
+ BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, dev_class);
+ if ((BTM_ReadRemoteDeviceName(bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
+ return BTM_CMD_STARTED;
+
+ APPL_TRACE_WARNING0(" bta_dm_pin_cback() -> Failed to start Remote Name Request ");
+ }
+
+ bdcpy(sec_event.pin_req.bd_addr, bd_addr);
+ BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, dev_class);
+ BCM_STRNCPY_S((char*)sec_event.pin_req.bd_name, sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+ sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+
+ bta_dm_cb.p_sec_cback(BTA_DM_PIN_REQ_EVT, &sec_event);
+ return BTM_CMD_STARTED;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_dm_link_key_request_cback
+**
+** Description Callback requesting linkkey
+**
+** Returns void
+**
+*******************************************************************************/
+static UINT8 bta_dm_link_key_request_cback (BD_ADDR bd_addr, LINK_KEY key)
+{
+ /* Application passes all link key to
+ BTM during initialization using add_device
+ API. If BTM doesn't have the link key in it's
+ data base, that's because application doesn't
+ it */
+
+ return BTM_NOT_AUTHORIZED;
+}
+
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_dm_new_link_key_cback
+**
+** Description Callback from BTM to notify new link key
+**
+** Returns void
+**
+*******************************************************************************/
+static UINT8 bta_dm_new_link_key_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,
+ BD_NAME bd_name, LINK_KEY key, UINT8 key_type)
+{
+ tBTA_DM_SEC sec_event;
+ tBTA_DM_AUTH_CMPL *p_auth_cmpl;
+ UINT8 event;
+
+ memset (&sec_event, 0, sizeof(tBTA_DM_SEC));
+
+ /* Not AMP Key type */
+ if (key_type != HCI_LKEY_TYPE_AMP_WIFI && key_type != HCI_LKEY_TYPE_AMP_UWB)
+ {
+ event = BTA_DM_AUTH_CMPL_EVT;
+ p_auth_cmpl = &sec_event.auth_cmpl;
+
+ bdcpy(p_auth_cmpl->bd_addr, bd_addr);
+
+ memcpy(p_auth_cmpl->bd_name, bd_name, (BD_NAME_LEN-1));
+ p_auth_cmpl->bd_name[BD_NAME_LEN-1] = 0;
+
+ p_auth_cmpl->key_present = TRUE;
+ p_auth_cmpl->key_type = key_type;
+ p_auth_cmpl->success = TRUE;
+
+ memcpy(p_auth_cmpl->key, key, LINK_KEY_LEN);
+ sec_event.auth_cmpl.fail_reason = HCI_SUCCESS;
+
+ if(bta_dm_cb.p_sec_cback)
+ {
+ bta_dm_cb.p_sec_cback(event, &sec_event);
+ }
+ }
+ else
+ {
+ APPL_TRACE_WARNING0(" bta_dm_new_link_key_cback() Received AMP Key?? ");
+ }
+
+ return BTM_CMD_STARTED;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_authentication_complete_cback
+**
+** Description Authentication complete callback from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,BD_NAME bd_name, int result)
+{
+
+ tBTA_DM_SEC sec_event;
+
+ if(result != BTM_SUCCESS)
+ {
+ memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+ bdcpy(sec_event.auth_cmpl.bd_addr, bd_addr);
+
+ memcpy(sec_event.auth_cmpl.bd_name, bd_name, (BD_NAME_LEN-1));
+ sec_event.auth_cmpl.bd_name[BD_NAME_LEN-1] = 0;
+
+/* taken care of by memset [above]
+ sec_event.auth_cmpl.key_present = FALSE;
+ sec_event.auth_cmpl.success = FALSE;
+*/
+ sec_event.auth_cmpl.fail_reason = (UINT8)result;
+ if(bta_dm_cb.p_sec_cback)
+ {
+ bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+ }
+ }
+
+ return BTM_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_sp_cback
+**
+** Description simple pairing callback from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
+{
+ tBTM_STATUS status = BTM_CMD_STARTED;
+ tBTA_DM_SEC sec_event;
+ tBTA_DM_SEC_EVT pin_evt = BTA_DM_SP_KEY_NOTIF_EVT;
+
+ APPL_TRACE_EVENT1("bta_dm_sp_cback: %d", event);
+ if (!bta_dm_cb.p_sec_cback)
+ return BTM_NOT_AUTHORIZED;
+
+ /* TODO_SP */
+ switch(event)
+ {
+ case BTM_SP_IO_REQ_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+ /* translate auth_req */
+ bta_dm_co_io_req(p_data->io_req.bd_addr, &p_data->io_req.io_cap,
+ &p_data->io_req.oob_data, &p_data->io_req.auth_req, p_data->io_req.is_orig);
+#endif
+#if BTM_OOB_INCLUDED == FALSE
+ status = BTM_SUCCESS;
+#endif
+
+ APPL_TRACE_EVENT2("io mitm: %d oob_data:%d", p_data->io_req.auth_req, p_data->io_req.oob_data);
+ break;
+ case BTM_SP_IO_RSP_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+ bta_dm_co_io_rsp(p_data->io_rsp.bd_addr, p_data->io_rsp.io_cap,
+ p_data->io_rsp.oob_data, p_data->io_rsp.auth_req );
+#endif
+ break;
+
+ case BTM_SP_CFM_REQ_EVT:
+ pin_evt = BTA_DM_SP_CFM_REQ_EVT;
+ bta_dm_cb.just_works = sec_event.cfm_req.just_works = p_data->cfm_req.just_works;
+ sec_event.cfm_req.loc_auth_req = p_data->cfm_req.loc_auth_req;
+ sec_event.cfm_req.rmt_auth_req = p_data->cfm_req.rmt_auth_req;
+ sec_event.cfm_req.loc_io_caps = p_data->cfm_req.loc_io_caps;
+ sec_event.cfm_req.rmt_io_caps = p_data->cfm_req.rmt_io_caps;
+ /* continue to next case */
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+ /* Passkey entry mode, mobile device with output capability is very
+ unlikely to receive key request, so skip this event */
+ /*case BTM_SP_KEY_REQ_EVT: */
+ case BTM_SP_KEY_NOTIF_EVT:
+#endif
+ bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
+ /* If the device name is not known, save bdaddr and devclass and initiate a name request */
+ if (p_data->key_notif.bd_name[0] == 0)
+ {
+ bta_dm_cb.pin_evt = pin_evt;
+ bdcpy(bta_dm_cb.pin_bd_addr, p_data->key_notif.bd_addr);
+ BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->key_notif.dev_class);
+ if ((BTM_ReadRemoteDeviceName(p_data->key_notif.bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
+ return BTM_CMD_STARTED;
+
+ APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request ");
+ }
+ bdcpy(sec_event.key_notif.bd_addr, p_data->key_notif.bd_addr);
+ BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->key_notif.dev_class);
+ BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), (char*)p_data->key_notif.bd_name, (BD_NAME_LEN-1));
+ sec_event.key_notif.bd_name[BD_NAME_LEN-1] = 0;
+
+ bta_dm_cb.p_sec_cback(pin_evt, &sec_event);
+
+ break;
+
+#if BTM_OOB_INCLUDED == TRUE
+ case BTM_SP_LOC_OOB_EVT:
+ bta_dm_co_loc_oob((BOOLEAN)(p_data->loc_oob.status == BTM_SUCCESS),
+ p_data->loc_oob.c, p_data->loc_oob.r);
+ break;
+
+ case BTM_SP_RMT_OOB_EVT:
+ /* If the device name is not known, save bdaddr and devclass and initiate a name request */
+ if (p_data->rmt_oob.bd_name[0] == 0)
+ {
+ bta_dm_cb.pin_evt = BTA_DM_SP_RMT_OOB_EVT;
+ bdcpy(bta_dm_cb.pin_bd_addr, p_data->rmt_oob.bd_addr);
+ BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->rmt_oob.dev_class);
+ if ((BTM_ReadRemoteDeviceName(p_data->rmt_oob.bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
+ return BTM_CMD_STARTED;
+
+ APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request ");
+ }
+ bdcpy(sec_event.rmt_oob.bd_addr, p_data->rmt_oob.bd_addr);
+ BTA_COPY_DEVICE_CLASS(sec_event.rmt_oob.dev_class, p_data->rmt_oob.dev_class);
+ BCM_STRNCPY_S((char*)sec_event.rmt_oob.bd_name, sizeof(BD_NAME), (char*)p_data->rmt_oob.bd_name, (BD_NAME_LEN-1));
+ sec_event.rmt_oob.bd_name[BD_NAME_LEN-1] = 0;
+
+ bta_dm_cb.p_sec_cback(BTA_DM_SP_RMT_OOB_EVT, &sec_event);
+
+ bta_dm_co_rmt_oob(p_data->rmt_oob.bd_addr);
+ break;
+#endif
+ case BTM_SP_COMPLT_EVT:
+ /* do not report this event - handled by link_key_callback or auth_complete_callback */
+ break;
+
+ case BTM_SP_KEYPRESS_EVT:
+ memcpy(&sec_event.key_press, &p_data->key_press, sizeof(tBTM_SP_KEYPRESS));
+ bta_dm_cb.p_sec_cback(BTA_DM_SP_KEYPRESS_EVT, &sec_event);
+ break;
+
+ case BTM_SP_UPGRADE_EVT:
+ bta_dm_co_lk_upgrade(p_data->upgrade.bd_addr, &p_data->upgrade.upgrade );
+ break;
+
+ default:
+ status = BTM_NOT_AUTHORIZED;
+ break;
+ }
+ APPL_TRACE_EVENT1("dm status: %d", status);
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_local_name_cback
+**
+** Description Callback from btm after local name is read
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_local_name_cback(UINT8 *p_name)
+{
+ tBTA_DM_SEC sec_event;
+
+ BTM_GetLocalDeviceAddr(sec_event.enable.bd_addr);
+ sec_event.enable.status = BTA_SUCCESS;
+
+ if(bta_dm_cb.p_sec_cback)
+ bta_dm_cb.p_sec_cback(BTA_DM_ENABLE_EVT, &sec_event);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_signal_strength
+**
+** Description Callback from btm after local bdaddr is read
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_signal_strength(tBTA_DM_MSG *p_data)
+{
+
+ if(p_data->sig_strength.start)
+ {
+ bta_dm_cb.signal_strength_mask = p_data->sig_strength.mask;
+ bta_dm_cb.signal_strength_period = p_data->sig_strength.period;
+ bta_dm_signal_strength_timer_cback(NULL);
+ }
+ else
+ {
+ bta_sys_stop_timer(&bta_dm_cb.signal_strength_timer);
+ }
+
+}
+/*******************************************************************************
+**
+** Function bta_dm_signal_strength_timer_cback
+**
+** Description Periodic timer callback to read signal strength
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_signal_strength_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+
+ UINT8 i;
+
+ if(bta_dm_cb.signal_strength_mask & BTA_SIG_STRENGTH_RSSI_MASK)
+ {
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ BTM_ReadRSSI (bta_dm_cb.device_list.peer_device[i].peer_bdaddr, (tBTM_CMPL_CB *)bta_dm_rssi_cback);
+
+ }
+ }
+ if(bta_dm_cb.signal_strength_mask & BTA_SIG_STRENGTH_LINK_QUALITY_MASK)
+ {
+
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ BTM_ReadLinkQuality (bta_dm_cb.device_list.peer_device[i].peer_bdaddr, (tBTM_CMPL_CB *)bta_dm_link_quality_cback);
+ }
+
+ }
+
+ if(bta_dm_cb.signal_strength_period)
+ {
+ bta_dm_cb.signal_strength_timer.p_cback = (TIMER_CBACK*)&bta_dm_signal_strength_timer_cback;
+ bta_sys_start_timer(&bta_dm_cb.signal_strength_timer, 0, (UINT32)1000*bta_dm_cb.signal_strength_period);
+ }
+}
+
+
+#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function bta_dm_bl_change_cback
+**
+** Description Callback from btm when acl connection goes up or down
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data)
+{
+
+ tBTA_DM_ACL_CHANGE * p_msg;
+
+ if ((p_msg = (tBTA_DM_ACL_CHANGE *) GKI_getbuf(sizeof(tBTA_DM_ACL_CHANGE))) != NULL)
+ {
+ p_msg->event = p_data->event;
+ p_msg->is_new = FALSE;
+
+ switch(p_msg->event)
+ {
+ case BTM_BL_CONN_EVT:
+ p_msg->is_new = TRUE;
+ bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
+ break;
+ case BTM_BL_DISCN_EVT:
+ bdcpy(p_msg->bd_addr, p_data->discn.p_bda);
+ break;
+ case BTM_BL_UPDATE_EVT:
+ p_msg->busy_level = p_data->update.busy_level;
+ break;
+ case BTM_BL_ROLE_CHG_EVT:
+ p_msg->new_role = p_data->role_chg.new_role;
+ p_msg->hci_status = p_data->role_chg.hci_status;
+ bdcpy(p_msg->bd_addr, p_data->role_chg.p_bda);
+ break;
+ case BTM_BL_COLLISION_EVT:
+ bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
+ break;;
+ }
+
+ p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
+ bta_sys_sendmsg(p_msg);
+
+ }
+
+}
+#else
+
+/*******************************************************************************
+**
+** Function bta_dm_acl_change_cback
+**
+** Description Callback from btm when acl connection goes up or down
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_acl_change_cback (BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn,
+ BD_FEATURES features, BOOLEAN is_new)
+{
+
+ tBTA_DM_ACL_CHANGE * p_msg;
+
+ if ((p_msg = (tBTA_DM_ACL_CHANGE *) GKI_getbuf(sizeof(tBTA_DM_ACL_CHANGE))) != NULL)
+ {
+ bdcpy (p_msg->bd_addr, p_bda);
+ p_msg->is_new = is_new;
+
+ /* This is collision case */
+ if (features != NULL)
+ {
+ if ((features[0] == 0xFF) && !is_new)
+ p_msg->event = BTM_BL_COLLISION_EVT;
+ }
+
+ p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
+ bta_sys_sendmsg(p_msg);
+
+ }
+
+}
+#endif
+/*******************************************************************************
+**
+** Function bta_dm_rs_cback
+**
+** Description Receives the role switch complete event
+**
+** Returns
+**
+*******************************************************************************/
+static void bta_dm_rs_cback (tBTM_ROLE_SWITCH_CMPL *p1)
+{
+ APPL_TRACE_WARNING1("bta_dm_rs_cback:%d", bta_dm_cb.rs_event);
+ if(bta_dm_cb.rs_event == BTA_DM_API_SEARCH_EVT)
+ {
+ bta_dm_cb.search_msg.rs_res = BTA_DM_RS_OK; /* do not care about the result for now */
+ bta_dm_cb.rs_event = 0;
+ bta_dm_search_start((tBTA_DM_MSG *)&bta_dm_cb.search_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_check_av
+**
+** Description This function checks if AV is active
+** if yes, make sure the AV link is master
+**
+** Returns BOOLEAN - TRUE, if switch is in progress
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_check_av(UINT16 event)
+{
+ BOOLEAN switching = FALSE;
+ UINT8 i;
+ tBTA_DM_PEER_DEVICE *p_dev;
+
+ APPL_TRACE_WARNING1("bta_dm_check_av:%d", bta_dm_cb.cur_av_count);
+ if(bta_dm_cb.cur_av_count)
+ {
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ p_dev = &bta_dm_cb.device_list.peer_device[i];
+ APPL_TRACE_WARNING3("[%d]: state:%d, info:x%x", i, p_dev->conn_state, p_dev->info);
+ if((p_dev->conn_state == BTA_DM_CONNECTED) && (p_dev->info & BTA_DM_DI_AV_ACTIVE))
+ {
+ /* make master and take away the role switch policy */
+ if(BTM_CMD_STARTED == BTM_SwitchRole (p_dev->peer_bdaddr, HCI_ROLE_MASTER, (tBTM_CMPL_CB *)bta_dm_rs_cback))
+ {
+ /* the role switch command is actually sent */
+ bta_dm_cb.rs_event = event;
+ switching = TRUE;
+ }
+ /* else either already master or can not switch for some reasons */
+ bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_dev->peer_bdaddr);
+ break;
+ }
+ }
+ }
+ return switching;
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_acl_change
+**
+** Description Process BTA_DM_ACL_CHANGE_EVT
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_acl_change(tBTA_DM_MSG *p_data)
+{
+
+ UINT8 i;
+ UINT8 *p;
+ tBTA_DM_SEC conn;
+ BOOLEAN is_new = p_data->acl_change.is_new;
+ BD_ADDR_PTR p_bda = p_data->acl_change.bd_addr;
+ BOOLEAN need_policy_change = FALSE;
+ BOOLEAN issue_unpair_cb = FALSE;
+
+#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
+ tBTA_DM_PEER_DEVICE *p_dev;
+
+ switch(p_data->acl_change.event)
+ {
+ case BTM_BL_UPDATE_EVT: /* busy level update */
+ if( bta_dm_cb.p_sec_cback )
+ {
+ conn.busy_level.level = p_data->acl_change.busy_level;
+ bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);
+ }
+ return;
+
+ case BTM_BL_ROLE_CHG_EVT: /* role change event */
+ p_dev = bta_dm_find_peer_device(p_bda);
+ if(p_dev)
+ {
+ APPL_TRACE_DEBUG3("bta_dm_acl_change role chg info:x%x new_role:%d dev count:%d",
+ p_dev->info, p_data->acl_change.new_role, bta_dm_cb.device_list.count);
+ if(p_dev->info & BTA_DM_DI_AV_ACTIVE)
+ {
+ /* there's AV activity on this link */
+ if(p_data->acl_change.new_role == HCI_ROLE_SLAVE && bta_dm_cb.device_list.count > 1
+ && p_data->acl_change.hci_status == HCI_SUCCESS)
+ {
+ /* more than one connections and the AV connection is role switched to slave
+ * switch it back to master and remove the switch policy */
+ BTM_SwitchRole(p_bda, BTM_ROLE_MASTER, NULL);
+ need_policy_change = TRUE;
+ }
+ else if (bta_dm_cfg.avoid_scatter && (p_data->acl_change.new_role == HCI_ROLE_MASTER))
+ {
+ /* if the link updated to be master include AV activities, remove the switch policy */
+ need_policy_change = TRUE;
+ }
+
+ if(need_policy_change)
+ {
+ bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_dev->peer_bdaddr);
+ }
+ }
+ else
+ {
+ /* there's AV no activity on this link and role switch happened
+ * check if AV is active
+ * if so, make sure the AV link is master */
+ bta_dm_check_av(0);
+ }
+ bta_sys_notify_role_chg(p_data->acl_change.bd_addr, p_data->acl_change.new_role, p_data->acl_change.hci_status);
+ bdcpy(conn.role_chg.bd_addr, p_bda);
+ conn.role_chg.new_role = (UINT8) p_data->acl_change.new_role;
+ if( bta_dm_cb.p_sec_cback )
+ bta_dm_cb.p_sec_cback(BTA_DM_ROLE_CHG_EVT, &conn);
+ }
+ return;
+ }
+#endif
+
+ /* Collision report from Stack: Notify profiles */
+ if (p_data->acl_change.event == BTM_BL_COLLISION_EVT)
+ {
+ bta_sys_notify_collision (p_bda);
+ return;
+ }
+
+ if(is_new)
+ {
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda))
+ break;
+
+ }
+
+ if(i == bta_dm_cb.device_list.count)
+ {
+ bdcpy(bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].peer_bdaddr, p_bda);
+ bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].link_policy = bta_dm_cb.cur_policy;
+ bta_dm_cb.device_list.count++;
+ }
+
+ bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_CONNECTED;
+ bta_dm_cb.device_list.peer_device[i].pref_role = BTA_ANY_ROLE;
+ bdcpy(conn.link_up.bd_addr, p_bda);
+ bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_NONE;
+ if( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+ ((NULL != (p = BTM_ReadRemoteFeatures (p_bda))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) )
+ {
+ /* both local and remote devices support SSR */
+ bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_USE_SSR;
+ }
+ APPL_TRACE_WARNING1("info:x%x", bta_dm_cb.device_list.peer_device[i].info);
+ if( bta_dm_cb.p_sec_cback )
+ bta_dm_cb.p_sec_cback(BTA_DM_LINK_UP_EVT, &conn);
+
+ }
+ else
+ {
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ if(bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda))
+ continue;
+
+ if( bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING )
+ {
+ BTM_SecDeleteDevice(bta_dm_cb.device_list.peer_device[i].peer_bdaddr);
+ issue_unpair_cb = TRUE;
+ }
+
+ for(; i<bta_dm_cb.device_list.count ; i++)
+ {
+ memcpy(&bta_dm_cb.device_list.peer_device[i], &bta_dm_cb.device_list.peer_device[i+1], sizeof(bta_dm_cb.device_list.peer_device[i]));
+ }
+ break;
+ }
+ if(bta_dm_cb.device_list.count)
+ bta_dm_cb.device_list.count--;
+
+ if(bta_dm_search_cb.wait_disc && !bdcmp(bta_dm_search_cb.peer_bdaddr, p_bda))
+ {
+ bta_dm_search_cb.wait_disc = FALSE;
+
+ if(bta_dm_search_cb.sdp_results)
+ {
+ APPL_TRACE_EVENT0(" timer stopped ");
+ bta_sys_stop_timer(&bta_dm_search_cb.search_timer);
+ bta_dm_discover_next_device();
+ }
+
+ }
+
+ if(bta_dm_cb.disabling)
+ {
+ if(!BTM_GetNumAclLinks())
+ {
+ bta_sys_stop_timer(&bta_dm_cb.disable_timer);
+ bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_conn_down_timer_cback;
+ /* start a timer to make sure that the profiles get the disconnect event */
+ bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1000);
+ }
+ }
+
+ bdcpy(conn.link_down.bd_addr, p_bda);
+ conn.link_down.status = (UINT8) btm_get_acl_disc_reason_code();
+ if( bta_dm_cb.p_sec_cback )
+ {
+ bta_dm_cb.p_sec_cback(BTA_DM_LINK_DOWN_EVT, &conn);
+ if( issue_unpair_cb )
+ bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn);
+ }
+ }
+
+ bta_dm_adjust_roles(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_disable_conn_down_timer_cback
+**
+** Description Sends disable event to application
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+ tBTA_SYS_HW_MSG *sys_enable_event;
+
+ /* register our callback to SYS HW manager */
+ bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
+
+ /* send a message to BTA SYS */
+ if ((sys_enable_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+ {
+ sys_enable_event->hdr.event = BTA_SYS_API_DISABLE_EVT;
+ sys_enable_event->hw_module = BTA_SYS_HW_BLUETOOTH;
+ bta_sys_sendmsg(sys_enable_event);
+ }
+
+ bta_dm_cb.disabling = FALSE;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_rssi_cback
+**
+** Description Callback from btm with rssi values
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_rssi_cback (tBTM_RSSI_RESULTS *p_result)
+{
+ tBTA_DM_SEC sec_event;
+
+ if(p_result->status == BTM_SUCCESS)
+ {
+
+ bdcpy(sec_event.sig_strength.bd_addr, p_result->rem_bda);
+ sec_event.sig_strength.mask = BTA_SIG_STRENGTH_RSSI_MASK;
+ sec_event.sig_strength.rssi_value = p_result->rssi;
+ if( bta_dm_cb.p_sec_cback!= NULL )
+ bta_dm_cb.p_sec_cback(BTA_DM_SIG_STRENGTH_EVT, &sec_event);
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_link_quality_cback
+**
+** Description Callback from btm with link quality value
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_link_quality_cback (tBTM_LINK_QUALITY_RESULTS *p_result)
+{
+
+ tBTA_DM_SEC sec_event;
+
+ if(p_result->status == BTM_SUCCESS)
+ {
+
+ bdcpy(sec_event.sig_strength.bd_addr, p_result->rem_bda);
+ sec_event.sig_strength.mask = BTA_SIG_STRENGTH_LINK_QUALITY_MASK;
+ sec_event.sig_strength.link_quality_value = p_result->link_quality;
+ if( bta_dm_cb.p_sec_cback!= NULL )
+ bta_dm_cb.p_sec_cback(BTA_DM_SIG_STRENGTH_EVT, &sec_event);
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_rm_cback
+**
+** Description Role management callback from sys
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+
+ UINT8 j;
+ tBTA_PREF_ROLES role;
+ tBTA_DM_PEER_DEVICE *p_dev;
+
+ p_dev = bta_dm_find_peer_device(peer_addr);
+ if( status == BTA_SYS_CONN_OPEN)
+ {
+ if(p_dev)
+ {
+ /* Do not set to connected if we are in the middle of unpairing. When AV stream is
+ * started it fakes out a SYS_CONN_OPEN to potentially trigger a role switch command.
+ * But this should not be done if we are in the middle of unpairing.
+ */
+ if (p_dev->conn_state != BTA_DM_UNPAIRING)
+ p_dev->conn_state = BTA_DM_CONNECTED;
+
+ for(j=1; j<= p_bta_dm_rm_cfg[0].app_id; j++)
+ {
+ if(((p_bta_dm_rm_cfg[j].app_id == app_id) || (p_bta_dm_rm_cfg[j].app_id == BTA_ALL_APP_ID))
+ && (p_bta_dm_rm_cfg[j].id == id))
+ {
+ role = p_bta_dm_rm_cfg[j].cfg;
+
+ if(role > p_dev->pref_role )
+ p_dev->pref_role = role;
+ break;
+ }
+ }
+
+ }
+
+ }
+
+ if((BTA_ID_AV == id)||(BTA_ID_AVK ==id))
+ {
+ if( status == BTA_SYS_CONN_BUSY)
+ {
+ if(p_dev)
+ p_dev->info |= BTA_DM_DI_AV_ACTIVE;
+ /* AV calls bta_sys_conn_open with the A2DP stream count as app_id */
+ if(BTA_ID_AV == id)
+ bta_dm_cb.cur_av_count = app_id;
+ }
+ else if( status == BTA_SYS_CONN_IDLE)
+ {
+ if(p_dev)
+ p_dev->info &= ~BTA_DM_DI_AV_ACTIVE;
+ /* AV calls bta_sys_conn_open with the A2DP stream count as app_id */
+ if(BTA_ID_AV == id)
+ bta_dm_cb.cur_av_count = app_id;
+ }
+ APPL_TRACE_WARNING2("bta_dm_rm_cback:%d, status:%d", bta_dm_cb.cur_av_count, status);
+ }
+
+
+ bta_dm_adjust_roles(FALSE);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_dev_blacklisted_for_switch
+**
+** Description Checks if the device is blacklisted for immediate role switch after connection.
+**
+** Returns TRUE if dev is blacklisted else FALSE
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_dev_blacklisted_for_switch (BD_ADDR remote_bd_addr)
+{
+ UINT16 manufacturer = 0;
+ UINT16 lmp_sub_version = 0;
+ UINT8 lmp_version = 0;
+ UINT8 i = 0;
+
+ if (BTM_ReadRemoteVersion(remote_bd_addr, &lmp_version,
+ &manufacturer, &lmp_sub_version) == BTM_SUCCESS)
+ {
+ /* Check if this device version info matches with is
+ blacklisted versions for role switch */
+ for (i = 0; i < BTA_DM_MAX_ROLE_SWITCH_BLACKLIST_COUNT; i++)
+ {
+ if ((bta_role_switch_blacklist[i].lmp_version == lmp_version) &&
+ (bta_role_switch_blacklist[i].manufacturer == manufacturer)&&
+ ((bta_role_switch_blacklist[i].lmp_sub_version & lmp_sub_version) ==
+ bta_role_switch_blacklist[i].lmp_sub_version))
+ {
+ APPL_TRACE_EVENT0("Black list F/W version matches.. Delay Role Switch...");
+ return TRUE;
+ }
+
+ }
+ }
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_delay_role_switch_cback
+**
+** Description Callback from btm to delay a role switch
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle)
+{
+ APPL_TRACE_EVENT0("bta_dm_delay_role_switch_cback: initiating Delayed RS");
+ bta_dm_adjust_roles (FALSE);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_adjust_roles
+**
+** Description Adjust roles
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_adjust_roles(BOOLEAN delay_role_switch)
+{
+
+ UINT8 i;
+ BOOLEAN set_master_role = FALSE;
+
+ if(bta_dm_cb.device_list.count)
+ {
+
+ /* the configuration is no scatternet
+ * or AV connection exists and there are more than one ACL link */
+ if( (p_bta_dm_rm_cfg[0].cfg == BTA_DM_NO_SCATTERNET) ||
+ (bta_dm_cb.cur_av_count && bta_dm_cb.device_list.count > 1) )
+ {
+
+ L2CA_SetDesireRole (HCI_ROLE_MASTER);
+ set_master_role = TRUE;
+
+ }
+
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ if(bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED)
+ {
+ if(!set_master_role && (bta_dm_cb.device_list.peer_device[i].pref_role != BTA_ANY_ROLE)
+ && (p_bta_dm_rm_cfg[0].cfg == BTA_DM_PARTIAL_SCATTERNET))
+ {
+ L2CA_SetDesireRole (HCI_ROLE_MASTER);
+ set_master_role = TRUE;
+ }
+
+ if((bta_dm_cb.device_list.peer_device[i].pref_role == BTA_MASTER_ROLE_ONLY)
+ || (bta_dm_cb.device_list.count > 1))
+ {
+
+ /* Initiating immediate role switch with certain remote devices
+ has caused issues due to role switch colliding with link encryption setup and
+ causing encryption (and in turn the link) to fail . These device . Firmware
+ versions are stored in a blacklist and role switch with these devices are
+ delayed to avoid the collision with link encryption setup */
+
+ if ((delay_role_switch == FALSE) ||
+ (bta_dm_dev_blacklisted_for_switch(
+ bta_dm_cb.device_list.peer_device[i].peer_bdaddr) == FALSE))
+ {
+ BTM_SwitchRole (bta_dm_cb.device_list.peer_device[i].peer_bdaddr,
+ HCI_ROLE_MASTER, NULL);
+ }
+ else
+ {
+ bta_dm_cb.switch_delay_timer.p_cback =
+ (TIMER_CBACK*)&bta_dm_delay_role_switch_cback;
+ bta_sys_start_timer(&bta_dm_cb.switch_delay_timer, 0, 500);
+ }
+ }
+
+ }
+ }
+
+
+ if(!set_master_role)
+ {
+
+ L2CA_SetDesireRole (L2CAP_DESIRED_LINK_ROLE);
+
+ }
+
+ }
+ else
+ {
+ L2CA_SetDesireRole (L2CAP_DESIRED_LINK_ROLE);
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_get_remname
+**
+** Description Returns a pointer to the remote name stored in the DM control
+** block if it exists, or from the BTM memory.
+**
+** Returns char * - Pointer to the remote device name
+*******************************************************************************/
+static char *bta_dm_get_remname(void)
+{
+ char *p_name = bta_dm_search_cb.peer_name;
+ char *p_temp;
+
+ /* If the name isn't already stored, try retrieving from BTM */
+ if (*p_name == '\0')
+ if ((p_temp = BTM_SecReadDevName(bta_dm_search_cb.peer_bdaddr)) != NULL)
+ p_name = p_temp;
+
+ return p_name;
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_bond_cancel_complete_cback
+**
+** Description Authentication complete callback from BTM
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_bond_cancel_complete_cback(tBTM_STATUS result)
+{
+
+ tBTA_DM_SEC sec_event;
+
+ if (result == BTM_SUCCESS)
+ sec_event.bond_cancel_cmpl.result = BTA_SUCCESS;
+ else
+ sec_event.bond_cancel_cmpl.result = BTA_FAILURE;
+
+ if(bta_dm_cb.p_sec_cback)
+ {
+ bta_dm_cb.p_sec_cback(BTA_DM_BOND_CANCEL_CMPL_EVT, &sec_event);
+ }
+}
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
+ #if ( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+/*******************************************************************************
+**
+** Function bta_dm_update_eir_uuid
+**
+** Description
+**
+**
+*******************************************************************************/
+void bta_dm_update_eir_uuid (tBTA_DM_MSG *p_data)
+{
+ tBTA_DM_API_UPDATE_EIR_UUID *p_msg = (tBTA_DM_API_UPDATE_EIR_UUID *)p_data;
+ UINT8 xx;
+ UINT8 empty_slot = BTA_EIR_SERVER_NUM_CUSTOM_UUID;
+ UINT8 match_slot = BTA_EIR_SERVER_NUM_CUSTOM_UUID;
+
+ for (xx = 0; xx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; xx++)
+ {
+ if (bta_dm_cb.custom_uuid[xx].len == 0)
+ {
+ if (empty_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+ empty_slot = xx;
+ }
+ else if (match_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+ {
+ if (!memcmp (bta_dm_cb.custom_uuid[xx].uu.uuid128, p_msg->uuid.uu.uuid128, p_msg->uuid.len))
+ {
+ match_slot = xx;;
+ }
+ }
+ }
+
+ if (p_msg->is_add)
+ {
+ if (match_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+ {
+ if (empty_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+ {
+ APPL_TRACE_ERROR0("No space to add UUID for EIR");
+ return;
+ }
+ else
+ {
+ memcpy (&(bta_dm_cb.custom_uuid[empty_slot]), &(p_msg->uuid), sizeof(tBT_UUID));
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("UUID is already added for EIR");
+ return;
+ }
+ }
+ else
+ {
+ if (match_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+ {
+ APPL_TRACE_ERROR0("UUID is not found for EIR");
+ return;
+ }
+ else
+ {
+ memset (&(bta_dm_cb.custom_uuid[match_slot]), 0, sizeof(tBT_UUID));
+ }
+ }
+
+ bta_dm_set_eir (NULL);
+}
+ #endif
+
+/*******************************************************************************
+**
+** Function bta_dm_set_eir_config
+**
+** Description
+**
+**
+*******************************************************************************/
+void bta_dm_set_eir_config (tBTA_DM_MSG *p_data)
+{
+ if (p_data->set_eir_cfg.p_eir_cfg)
+ {
+ /* User defined config */
+ p_bta_dm_eir_cfg = p_data->set_eir_cfg.p_eir_cfg;
+ }
+ else
+ {
+ /* Back to default config */
+ p_bta_dm_eir_cfg = (tBTA_DM_EIR_CONF*)&bta_dm_eir_cfg;
+ }
+
+ bta_dm_set_eir (NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_set_eir
+**
+** Description This function creates EIR tagged data and writes it to controller.
+**
+** Returns None
+**
+*******************************************************************************/
+static void bta_dm_set_eir (char *local_name)
+{
+ BT_HDR *p_buf;
+ UINT8 *p;
+ UINT8 *p_length;
+#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
+ UINT8 *p_type;
+ UINT8 max_num_uuid;
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ UINT8 custom_uuid_idx;
+#endif
+#endif
+#if (BTM_EIR_DEFAULT_FEC_REQUIRED == FALSE)
+ UINT8 free_eir_length = HCI_EXT_INQ_RESPONSE_LEN;
+#else
+ UINT8 free_eir_length = HCI_DM5_PACKET_SIZE;
+#endif
+ UINT8 num_uuid;
+ UINT8 data_type;
+ UINT8 local_name_len;
+
+ /* wait until complete to disable */
+ if (bta_dm_cb.disable_timer.in_use)
+ return;
+
+#if ( BTA_EIR_CANNED_UUID_LIST != TRUE )
+ /* wait until App is ready */
+ if (bta_dm_cb.app_ready_timer.in_use)
+ return;
+
+ /* if local name is not provided, get it from controller */
+ if( local_name == NULL )
+ {
+ if( BTM_ReadLocalDeviceName( &local_name ) != BTM_SUCCESS )
+ {
+ APPL_TRACE_ERROR0("Fail to read local device name for EIR");
+ }
+ }
+#endif
+
+ /* Allocate a buffer to hold HCI command */
+ if ((p_buf = (BT_HDR *)GKI_getpoolbuf(BTM_CMD_POOL_ID)) == NULL)
+ {
+ APPL_TRACE_ERROR0("bta_dm_set_eir couldn't allocate buffer");
+ return;
+ }
+ p = (UINT8 *)p_buf + BTM_HCI_EIR_OFFSET;
+
+ memset(p, 0x00, HCI_EXT_INQ_RESPONSE_LEN );
+
+ APPL_TRACE_DEBUG0("BTA is generating EIR");
+
+ if( local_name )
+ local_name_len = strlen( local_name );
+ else
+ local_name_len = 0;
+
+ data_type = BTM_EIR_COMPLETE_LOCAL_NAME_TYPE;
+ /* if local name is longer than minimum length of shortened name */
+ /* check whether it needs to be shortened or not */
+ if( local_name_len > p_bta_dm_eir_cfg->bta_dm_eir_min_name_len )
+ {
+ /* get number of UUID 16-bit list */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+ num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len/LEN_UUID_16;
+#else
+ max_num_uuid = (free_eir_length - 2)/LEN_UUID_16;
+ data_type = BTM_GetEirSupportedServices( bta_dm_cb.eir_uuid, &p,
+ max_num_uuid, &num_uuid );
+ p = (UINT8 *)p_buf + BTM_HCI_EIR_OFFSET; /* reset p */
+#endif
+
+ /* if UUID doesn't fit remaing space, shorten local name */
+ if ( local_name_len > (free_eir_length - 4 - num_uuid*LEN_UUID_16))
+ {
+ APPL_TRACE_WARNING0("BTA EIR: local name is shortened");
+ local_name_len = p_bta_dm_eir_cfg->bta_dm_eir_min_name_len;
+ data_type = BTM_EIR_SHORTENED_LOCAL_NAME_TYPE;
+ }
+ else
+ data_type = BTM_EIR_COMPLETE_LOCAL_NAME_TYPE;
+ }
+
+ UINT8_TO_STREAM(p, local_name_len + 1);
+ UINT8_TO_STREAM(p, data_type);
+ memcpy(p, local_name, local_name_len);
+ p += local_name_len;
+ free_eir_length -= local_name_len + 2;
+
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+ /* if UUID list is provided as static data in configuration */
+ if(( p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len > 0 )
+ &&(p_bta_dm_eir_cfg->bta_dm_eir_uuid16))
+ {
+ if( free_eir_length > LEN_UUID_16 + 2)
+ {
+ free_eir_length -= 2;
+
+ if( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len)
+ {
+ num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len / LEN_UUID_16;
+ data_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
+ }
+ else /* not enough room for all UUIDs */
+ {
+ APPL_TRACE_WARNING0("BTA EIR: UUID 16-bit list is truncated");
+ num_uuid = free_eir_length / LEN_UUID_16;
+ data_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
+ }
+ UINT8_TO_STREAM(p, num_uuid * LEN_UUID_16 + 1);
+ UINT8_TO_STREAM(p, data_type);
+ memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_uuid16, num_uuid * LEN_UUID_16 );
+ p += num_uuid * LEN_UUID_16;
+ free_eir_length -= num_uuid * LEN_UUID_16;
+ }
+ }
+#else /* (BTA_EIR_CANNED_UUID_LIST == TRUE) */
+ /* if UUID list is dynamic */
+ if ( free_eir_length >= 2)
+ {
+ p_length = p++;
+ p_type = p++;
+ num_uuid = 0;
+
+ max_num_uuid = (free_eir_length - 2)/LEN_UUID_16;
+ data_type = BTM_GetEirSupportedServices( bta_dm_cb.eir_uuid, &p, max_num_uuid, &num_uuid );
+
+ if( data_type == BTM_EIR_MORE_16BITS_UUID_TYPE )
+ {
+ APPL_TRACE_WARNING0("BTA EIR: UUID 16-bit list is truncated");
+ }
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ else
+ {
+ for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+ {
+ if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_16)
+ {
+ if ( num_uuid < max_num_uuid )
+ {
+ UINT16_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid16);
+ num_uuid++;
+ }
+ else
+ {
+ data_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
+ APPL_TRACE_WARNING0("BTA EIR: UUID 16-bit list is truncated");
+ break;
+ }
+ }
+ }
+ }
+#endif /* (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0) */
+
+ UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_16 + 1);
+ UINT8_TO_STREAM(p_type, data_type);
+ free_eir_length -= num_uuid * LEN_UUID_16 + 2;
+ }
+#endif /* (BTA_EIR_CANNED_UUID_LIST == TRUE) */
+
+#if ( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ /* Adding 32-bit UUID list */
+ if ( free_eir_length >= 2)
+ {
+ p_length = p++;
+ p_type = p++;
+ num_uuid = 0;
+ data_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
+
+ max_num_uuid = (free_eir_length - 2)/LEN_UUID_32;
+
+ for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+ {
+ if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_32)
+ {
+ if ( num_uuid < max_num_uuid )
+ {
+ UINT32_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid32);
+ num_uuid++;
+ }
+ else
+ {
+ data_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
+ APPL_TRACE_WARNING0("BTA EIR: UUID 32-bit list is truncated");
+ break;
+ }
+ }
+ }
+
+ UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_32 + 1);
+ UINT8_TO_STREAM(p_type, data_type);
+ free_eir_length -= num_uuid * LEN_UUID_32 + 2;
+ }
+
+ /* Adding 128-bit UUID list */
+ if ( free_eir_length >= 2)
+ {
+ p_length = p++;
+ p_type = p++;
+ num_uuid = 0;
+ data_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
+
+ max_num_uuid = (free_eir_length - 2)/LEN_UUID_128;
+
+ for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+ {
+ if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_128)
+ {
+ if ( num_uuid < max_num_uuid )
+ {
+ ARRAY16_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid128);
+ num_uuid++;
+ }
+ else
+ {
+ data_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
+ APPL_TRACE_WARNING0("BTA EIR: UUID 128-bit list is truncated");
+ break;
+ }
+ }
+ }
+
+ UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_128 + 1);
+ UINT8_TO_STREAM(p_type, data_type);
+ free_eir_length -= num_uuid * LEN_UUID_128 + 2;
+ }
+#endif /* ( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0) */
+
+ /* if Flags are provided in configuration */
+ if(( p_bta_dm_eir_cfg->bta_dm_eir_flag_len > 0 )
+ &&( p_bta_dm_eir_cfg->bta_dm_eir_flags )
+ &&( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 2 ))
+ {
+ UINT8_TO_STREAM(p, p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 1);
+ UINT8_TO_STREAM(p, BTM_EIR_FLAGS_TYPE);
+ memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_flags,
+ p_bta_dm_eir_cfg->bta_dm_eir_flag_len);
+ p += p_bta_dm_eir_cfg->bta_dm_eir_flag_len;
+ free_eir_length -= p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 2;
+ }
+
+ /* if Inquiry Tx Resp Power compiled */
+ if((p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power) &&
+ (free_eir_length >= 3))
+ {
+ UINT8_TO_STREAM(p, 2); /* Length field */
+ UINT8_TO_STREAM(p, BTM_EIR_TX_POWER_LEVEL_TYPE);
+ UINT8_TO_STREAM(p, *(p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power));
+ free_eir_length -= 3;
+ }
+
+ /* if Manufacturer Specific are provided in configuration */
+ if(( p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len > 0 )
+ &&( p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec )
+ &&( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 2 ))
+ {
+ p_length = p;
+
+ UINT8_TO_STREAM(p, p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 1);
+ UINT8_TO_STREAM(p, BTM_EIR_MANUFACTURER_SPECIFIC_TYPE);
+ memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec,
+ p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len);
+ p += p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len;
+ free_eir_length -= p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 2;
+
+ }
+ else
+ {
+ p_length = NULL;
+ }
+
+ if( free_eir_length )
+ UINT8_TO_STREAM(p, 0); /* terminator of significant part */
+
+ BTM_WriteEIR( p_buf );
+
+}
+#endif
+
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function bta_dm_eir_search_services
+**
+** Description This function searches services in received EIR
+**
+** Returns None
+**
+*******************************************************************************/
+static void bta_dm_eir_search_services( tBTM_INQ_RESULTS *p_result,
+ tBTA_SERVICE_MASK *p_services_to_search,
+ tBTA_SERVICE_MASK *p_services_found)
+{
+ tBTA_SERVICE_MASK service_index = 0;
+ tBTM_EIR_SEARCH_RESULT result;
+
+ APPL_TRACE_DEBUG6("BTA searching services in EIR of BDA:0x%02X%02X%02X%02X%02X%02X",
+ p_result->remote_bd_addr[0],p_result->remote_bd_addr[1],
+ p_result->remote_bd_addr[2],p_result->remote_bd_addr[3],
+ p_result->remote_bd_addr[4],p_result->remote_bd_addr[5]);
+
+ APPL_TRACE_DEBUG1(" with services_to_search=0x%08X", *p_services_to_search);
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ /* always do GATT based service discovery by SDP instead of from EIR */
+ /* if GATT based service is also to be put in EIR, need to modify this */
+ while (service_index < (BTA_MAX_SERVICE_ID - 1))
+#else
+ while(service_index < BTA_MAX_SERVICE_ID)
+#endif
+ {
+ if( *p_services_to_search
+ & (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)))
+ {
+ result = BTM_HasInquiryEirService( p_result,
+ bta_service_id_to_uuid_lkup_tbl[service_index] );
+
+ /* Searching for HSP v1.2 only device */
+ if ((result != BTM_EIR_FOUND) &&
+ (bta_service_id_to_uuid_lkup_tbl[service_index] == UUID_SERVCLASS_HEADSET))
+ {
+ result = BTM_HasInquiryEirService (p_result, UUID_SERVCLASS_HEADSET_HS);
+ }
+
+ if( result == BTM_EIR_FOUND )
+ {
+ /* If Plug and Play service record, need to check to see if Broadcom stack */
+ /* However, EIR data doesn't have EXT_BRCM_VERSION so just skip it */
+ if( bta_service_id_to_uuid_lkup_tbl[service_index]
+ != UUID_SERVCLASS_PNP_INFORMATION )
+ {
+
+ *p_services_found |=
+ (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index));
+ /* remove the service from services to be searched */
+ *p_services_to_search &=
+ (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)));
+ }
+ }
+ else if( result == BTM_EIR_NOT_FOUND )
+ {
+ /* remove the service from services to be searched */
+ *p_services_to_search &=
+ (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)));
+ }
+ }
+
+ service_index++;
+ }
+
+ APPL_TRACE_ERROR2("BTA EIR search result, services_to_search=0x%08X, services_found=0x%08X",
+ *p_services_to_search, *p_services_found);
+}
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+/*******************************************************************************
+**
+** Function bta_dm_eir_update_uuid
+**
+** Description This function adds or removes service UUID in EIR database.
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding)
+{
+ /* if this UUID is not advertised in EIR */
+ if( !BTM_HasEirService( p_bta_dm_eir_cfg->uuid_mask, uuid16 ))
+ return;
+
+ if( adding )
+ {
+ APPL_TRACE_EVENT1("Adding UUID=0x%04X into EIR", uuid16);
+
+ BTM_AddEirService( bta_dm_cb.eir_uuid, uuid16 );
+ }
+ else
+ {
+ APPL_TRACE_EVENT1("Removing UUID=0x%04X from EIR", uuid16);
+
+ BTM_RemoveEirService( bta_dm_cb.eir_uuid, uuid16 );
+ }
+
+ bta_dm_set_eir (NULL);
+
+ APPL_TRACE_EVENT2("bta_dm_eir_update_uuid UUID bit mask=0x%08X %08X",
+ bta_dm_cb.eir_uuid[1], bta_dm_cb.eir_uuid[0] );
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_dm_enable_test_mode
+**
+** Description enable test mode
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data)
+{
+ BTM_EnableTestMode();
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_disable_test_mode
+**
+** Description disable test mode
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data)
+{
+ BTM_DeviceReset(NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_execute_callback
+**
+** Description Just execute a generic call back in the context of the BTU/BTA tack
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_execute_callback(tBTA_DM_MSG *p_data)
+{
+ /* sanity check */
+ if(p_data->exec_cback.p_exec_cback == NULL)
+ {
+ return;
+ }
+
+ p_data->exec_cback.p_exec_cback(p_data->exec_cback.p_param);
+}
+/*******************************************************************************
+**
+** Function bta_dm_encrypt_cback
+**
+** Description link encryption complete callback.
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_dm_encrypt_cback(BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
+{
+ tBTA_STATUS bta_status = BTA_SUCCESS;
+ tBTA_DM_ENCRYPT_CBACK *p_callback = bta_dm_cb.p_encrypt_cback;
+
+ bta_dm_cb.p_encrypt_cback = NULL;
+ switch (result)
+ {
+ case BTM_SUCCESS:
+ break;
+ case BTM_WRONG_MODE:
+ bta_status = BTA_WRONG_MODE;
+ break;
+ case BTM_NO_RESOURCES:
+ bta_status = BTA_NO_RESOURCES;
+ break;
+ case BTM_BUSY:
+ bta_status = BTA_BUSY;
+ break;
+ default:
+ bta_status = BTA_FAILURE;
+ break;
+ }
+
+ APPL_TRACE_DEBUG2("bta_dm_encrypt_cback status =%d p_callback=0x%x", bta_status, p_callback);
+
+ if (p_callback)
+ {
+ (*p_callback)(bd_addr, bta_status);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_dm_set_encryption
+**
+** Description This function to encrypt the link
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_dm_set_encryption (tBTA_DM_MSG *p_data)
+{
+
+ APPL_TRACE_DEBUG0("bta_dm_set_encryption"); //todo
+ if (!p_data->set_encryption.p_callback)
+ {
+ APPL_TRACE_ERROR0("bta_dm_set_encryption callback is not provided");
+ return;
+ }
+
+ if (bta_dm_cb.p_encrypt_cback)
+ {
+ (*p_data->set_encryption.p_callback)(p_data->set_encryption.bd_addr, BTA_BUSY);
+ return;
+ }
+
+
+ bta_dm_cb.p_encrypt_cback = p_data->set_encryption.p_callback;
+ bta_dm_cb.sec_act = p_data->set_encryption.sec_act;
+ BTM_SetEncryption(p_data->set_encryption.bd_addr, bta_dm_encrypt_cback, &bta_dm_cb.sec_act);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_set_afh_channels
+**
+** Description set afh channels
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_set_afh_channels(tBTA_DM_MSG * p_data)
+{
+
+ BTM_SetAfhChannels(p_data->set_afhchannels.first,p_data->set_afhchannels.last);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_set_afh_channel_assesment
+**
+** Description set afh channel assesment
+**
+**
+** Returns void
+**
+*******************************************************************************/
+
+void bta_dm_set_afh_channel_assesment (tBTA_DM_MSG * p_data)
+{
+ BTM_SetAfhChannelAssessment(p_data->set_afh_channel_assessment.enable_or_disable);
+}
+
+#if (BLE_INCLUDED == TRUE)
+#if (SMP_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function bta_dm_ble_smp_cback
+**
+** Description Callback for BLE SMP
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_DATA *p_data)
+{
+ tBTM_STATUS status = BTM_SUCCESS;
+ tBTA_DM_SEC sec_event;
+
+ if (!bta_dm_cb.p_sec_cback)
+ return BTM_NOT_AUTHORIZED;
+
+ memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+ switch (event)
+ {
+ case BTM_LE_IO_REQ_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+
+ bta_dm_co_ble_io_req(bda,
+ &p_data->io_req.io_cap,
+ &p_data->io_req.oob_data,
+ &p_data->io_req.auth_req,
+ &p_data->io_req.max_key_size,
+ &p_data->io_req.init_keys,
+ &p_data->io_req.resp_keys);
+#endif
+#if BTM_OOB_INCLUDED == FALSE
+ status = BTM_SUCCESS;
+#endif
+ APPL_TRACE_EVENT2("io mitm: %d oob_data:%d", p_data->io_req.auth_req, p_data->io_req.oob_data);
+
+ break;
+
+ case BTM_LE_SEC_REQUEST_EVT:
+ bdcpy(sec_event.ble_req.bd_addr, bda);
+ BCM_STRNCPY_S((char*)sec_event.ble_req.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+ bta_dm_cb.p_sec_cback(BTA_DM_BLE_SEC_REQ_EVT, &sec_event);
+ break;
+
+ case BTM_LE_KEY_NOTIF_EVT:
+ bdcpy(sec_event.key_notif.bd_addr, bda);
+ BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+ sec_event.key_notif.passkey = p_data->key_notif;
+ bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_NOTIF_EVT, &sec_event);
+ break;
+
+ case BTM_LE_KEY_REQ_EVT:
+ bdcpy(sec_event.ble_req.bd_addr, bda);
+ bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_REQ_EVT, &sec_event);
+ break;
+
+ case BTM_LE_OOB_REQ_EVT:
+ bdcpy(sec_event.ble_req.bd_addr, bda);
+ bta_dm_cb.p_sec_cback(BTA_DM_BLE_OOB_REQ_EVT, &sec_event);
+ break;
+
+ case BTM_LE_KEY_EVT:
+ bdcpy(sec_event.ble_key.bd_addr, bda);
+ sec_event.ble_key.key_type = p_data->key.key_type;
+ memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE));
+ bta_dm_cb.p_sec_cback(BTA_DM_BLE_KEY_EVT, &sec_event);
+ break;
+
+ case BTM_LE_COMPLT_EVT:
+ bdcpy(sec_event.auth_cmpl.bd_addr, bda);
+ if (p_data->complt.reason != 0)
+ sec_event.auth_cmpl.fail_reason = BTA_DM_AUTH_CONVERT_SMP_CODE(((UINT8)p_data->complt.reason));
+ else
+ sec_event.auth_cmpl.success = TRUE;
+
+ if (bta_dm_cb.p_sec_cback)
+ {
+ //bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+ bta_dm_cb.p_sec_cback(BTA_DM_BLE_AUTH_CMPL_EVT, &sec_event);
+ }
+
+ break;
+
+ default:
+ status = BTM_NOT_AUTHORIZED;
+ break;
+ }
+ return status;
+}
+#endif /* SMP_INCLUDED == TRUE */
+
+/*******************************************************************************
+**
+** Function bta_dm_ble_id_key_cback
+**
+** Description Callback for BLE local ID keys
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_ble_id_key_cback (UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key)
+{
+ UINT8 evt;
+ tBTA_DM_SEC dm_key;
+
+ switch (key_type)
+ {
+ case BTM_BLE_KEY_TYPE_ID:
+ case BTM_BLE_KEY_TYPE_ER:
+ if (bta_dm_cb.p_sec_cback)
+ {
+ memcpy(&dm_key.ble_id_keys, p_key, sizeof(tBTM_BLE_LOCAL_KEYS));
+
+ evt = (key_type == BTM_BLE_KEY_TYPE_ID) ? BTA_DM_BLE_LOCAL_IR_EVT :\
+ BTA_DM_BLE_LOCAL_ER_EVT;
+ bta_dm_cb.p_sec_cback(evt, &dm_key);
+ }
+ break;
+
+ default:
+ APPL_TRACE_DEBUG1("Unknown key type %d", key_type);
+ break;
+ }
+ return;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_add_blekey
+**
+** Description This function adds an BLE Key to an security database entry.
+** This function shall only be called AFTER BTA_DmAddBleDevice has been called.
+** It is normally called during host startup to restore all required information
+** stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_add_blekey (tBTA_DM_MSG *p_data)
+{
+ if (!BTM_SecAddBleKey (p_data->add_ble_key.bd_addr,
+ (tBTM_LE_KEY_VALUE *)&p_data->add_ble_key.blekey,
+ p_data->add_ble_key.key_type))
+ {
+ APPL_TRACE_ERROR2 ("BTA_DM: Error adding BLE Key for device %08x%04x",
+ (p_data->add_ble_key.bd_addr[0]<<24)+(p_data->add_ble_key.bd_addr[1]<<16)+\
+ (p_data->add_ble_key.bd_addr[2]<<8)+p_data->add_ble_key.bd_addr[3],
+ (p_data->add_ble_key.bd_addr[4]<<8)+p_data->add_ble_key.bd_addr[5]);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_add_ble_device
+**
+** Description This function adds an BLE device to an security database entry.
+** It is normally called during host startup to restore all required information
+** stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_add_ble_device (tBTA_DM_MSG *p_data)
+{
+ if (!BTM_SecAddBleDevice (p_data->add_ble_device.bd_addr, NULL,
+ p_data->add_ble_device.dev_type ,
+ p_data->add_ble_device.addr_type))
+ {
+ APPL_TRACE_ERROR2 ("BTA_DM: Error adding BLE Device for device %08x%04x",
+ (p_data->add_ble_device.bd_addr[0]<<24)+(p_data->add_ble_device.bd_addr[1]<<16)+ \
+ (p_data->add_ble_device.bd_addr[2]<<8)+p_data->add_ble_device.bd_addr[3],
+ (p_data->add_ble_device.bd_addr[4]<<8)+p_data->add_ble_device.bd_addr[5]);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_add_ble_device
+**
+** Description This function adds an BLE device to an security database entry.
+** It is normally called during host startup to restore all required information
+** stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data)
+{
+ if (p_data->pin_reply.accept)
+ {
+
+ BTM_BlePasskeyReply(p_data->ble_passkey_reply.bd_addr, BTM_SUCCESS, p_data->ble_passkey_reply.passkey);
+ }
+ else
+ {
+ BTM_BlePasskeyReply(p_data->ble_passkey_reply.bd_addr, BTM_NOT_AUTHORIZED, p_data->ble_passkey_reply.passkey);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_security_grant
+**
+** Description This function grant SMP security request access.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_security_grant (tBTA_DM_MSG *p_data)
+{
+ BTM_SecurityGrant(p_data->ble_sec_grant.bd_addr, p_data->ble_sec_grant.res);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_ble_set_bg_conn_type
+**
+** Description This function set the BLE background connection type
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data)
+{
+ BTM_BleSetBgConnType(p_data->ble_set_bd_conn_type.bg_conn_type,
+ p_data->ble_set_bd_conn_type.p_select_cback);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_ble_set_conn_params
+**
+** Description This function set the preferred connection parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data)
+{
+ BTM_BleSetPrefConnParams(p_data->ble_set_conn_params.peer_bda,
+ p_data->ble_set_conn_params.conn_int_min,
+ p_data->ble_set_conn_params.conn_int_max,
+ p_data->ble_set_conn_params.slave_latency,
+ p_data->ble_set_conn_params.supervision_tout);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_ble_set_scan_params
+**
+** Description This function set the preferred connection scan parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_scan_params (tBTA_DM_MSG *p_data)
+{
+ BTM_BleSetConnScanParams(p_data->ble_set_scan_params.scan_int,
+ p_data->ble_set_scan_params.scan_window);
+}
+
+#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+
+/*******************************************************************************
+**
+** Function btm_dm_start_disc_gatt_services
+**
+** Description This function starts a GATT service search request.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void btm_dm_start_disc_gatt_services (UINT16 conn_id)
+{
+ tBT_UUID *p_uuid = bta_dm_search_cb.p_srvc_uuid +
+ bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search;
+
+ p_uuid = bta_dm_search_cb.p_srvc_uuid +
+ bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search;
+
+ /* always search for all services */
+ BTA_GATTC_ServiceSearchRequest(conn_id, p_uuid);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_gatt_disc_result
+**
+** Description This function process the GATT service search result.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gatt_disc_result(tBTA_GATT_ID service_id)
+{
+ tBTA_DM_SEARCH result;
+
+ /*
+ * This logic will not work for gatt case. We are checking against the bluetooth profiles here
+ * just copy the GATTID in raw data field and send it across.
+ */
+
+
+ if ( bta_dm_search_cb.ble_raw_used + sizeof(tBTA_GATT_ID) < bta_dm_search_cb.ble_raw_size )
+ {
+ APPL_TRACE_DEBUG3("ADDING BLE SERVICE uuid=0x%x, ble_ptr = 0x%x, ble_raw_used = 0x%x", service_id.uuid.uu.uuid16,bta_dm_search_cb.p_ble_rawdata,bta_dm_search_cb.ble_raw_used);
+
+ memcpy((bta_dm_search_cb.p_ble_rawdata + bta_dm_search_cb.ble_raw_used), &service_id,
+ sizeof(service_id) );
+
+ bta_dm_search_cb.ble_raw_used += sizeof(service_id);
+
+ }
+ else
+ {
+ APPL_TRACE_ERROR3("%s out of room to accomodate more service ids ble_raw_size = %d ble_raw_used = %d", __FUNCTION__,bta_dm_search_cb.ble_raw_size, bta_dm_search_cb.ble_raw_used );
+ }
+
+ APPL_TRACE_ERROR1("bta_dm_gatt_disc_result serivce_id len=%d ", service_id.uuid.len);
+ if ( bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE)
+ {
+
+ /* send result back to app now, one by one */
+ bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+ memcpy(&result.disc_ble_res.service, &service_id.uuid, sizeof(tBT_UUID));
+
+ bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_gatt_disc_complete
+**
+** Description This function process the GATT service search complete.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gatt_disc_complete(UINT16 conn_id, tBTA_GATT_STATUS status)
+{
+ tBTA_DM_MSG *p_msg;
+
+ APPL_TRACE_DEBUG1("bta_dm_gatt_disc_complete conn_id = %d",conn_id);
+
+ if (bta_dm_search_cb.uuid_to_search > 0) bta_dm_search_cb.uuid_to_search --;
+
+ if (status == BTA_GATT_OK && bta_dm_search_cb.uuid_to_search > 0)
+ {
+ btm_dm_start_disc_gatt_services(conn_id);
+ }
+ else
+ {
+ bta_dm_search_cb.uuid_to_search = 0;
+
+ /* no more services to be discovered */
+ if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+ p_msg->disc_result.result.disc_res.result = (status == BTA_GATT_OK) ? BTA_SUCCESS :BTA_FAILURE;
+ p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+ bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+ BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+ bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+ /* make sure the string is terminated */
+ p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+ p_msg->disc_result.result.disc_res.device_type = BT_DEVICE_TYPE_BLE;
+ if ( bta_dm_search_cb.ble_raw_used > 0 )
+ {
+ p_msg->disc_result.result.disc_res.p_raw_data = GKI_getbuf(bta_dm_search_cb.ble_raw_used);
+
+ memcpy( p_msg->disc_result.result.disc_res.p_raw_data,
+ bta_dm_search_cb.p_ble_rawdata,
+ bta_dm_search_cb.ble_raw_used );
+
+ p_msg->disc_result.result.disc_res.raw_data_size = bta_dm_search_cb.ble_raw_used;
+ }
+ else
+ {
+ p_msg->disc_result.result.disc_res.p_raw_data = NULL;
+ bta_dm_search_cb.p_ble_rawdata = 0;
+ }
+
+ bta_sys_sendmsg(p_msg);
+ }
+ if (conn_id != BTA_GATT_INVALID_CONN_ID)
+ {
+ BTA_GATTC_Close(conn_id);
+ }
+ bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+ bta_dm_search_cb.gatt_disc_active = FALSE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btm_dm_start_gatt_discovery
+**
+** Description This is GATT initiate the service search by open a GATT connection
+** first.
+**
+** Parameters:
+**
+*******************************************************************************/
+void btm_dm_start_gatt_discovery (BD_ADDR bd_addr)
+{
+ bta_dm_search_cb.gatt_disc_active = TRUE;
+ BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, TRUE);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_cancel_gatt_discovery
+**
+** Description This is GATT cancel the GATT service search.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_cancel_gatt_discovery(BD_ADDR bd_addr)
+{
+ if (bta_dm_search_cb.conn_id == BTA_GATT_INVALID_CONN_ID)
+ {
+ BTA_GATTC_CancelOpen(bta_dm_search_cb.client_if, bd_addr, TRUE);
+ }
+
+ bta_dm_gatt_disc_complete(bta_dm_search_cb.conn_id, (tBTA_GATT_STATUS) BTA_GATT_ERROR);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_proc_open_evt
+**
+** Description process BTA_GATTC_OPEN_EVT in DM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_proc_open_evt(tBTA_GATTC_OPEN *p_data)
+{
+ UINT8 *p1;
+ UINT8 *p2;
+
+ p1 = bta_dm_search_cb.peer_bdaddr;
+ p2 = p_data->remote_bda;
+
+ APPL_TRACE_DEBUG5("DM Search state= %d search_cb.peer_dbaddr: [%08x%04x] connected_bda= [%08x%04x] ",
+ bta_dm_search_cb.state,
+ ((p1[0])<<24)+((p1[1])<<16)+((p1[2])<<8)+(p1[3]),
+ ((p1[4])<<8)+ p1[5],
+ ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
+ ((p2[4])<<8)+ p2[5]);
+
+ APPL_TRACE_DEBUG3("BTA_GATTC_OPEN_EVT conn_id = %d client_if=%d status = %d" ,
+ p_data->conn_id,
+ p_data->client_if,
+ p_data->status);
+
+ bta_dm_search_cb.conn_id = p_data->conn_id;
+
+ if (p_data->status == BTA_GATT_OK)
+ {
+ btm_dm_start_disc_gatt_services(p_data->conn_id);
+ }
+ else
+ {
+ bta_dm_gatt_disc_complete(BTA_GATT_INVALID_CONN_ID, p_data->status);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_gattc_callback
+**
+** Description This is GATT client callback function used in DM.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
+{
+ APPL_TRACE_DEBUG1("bta_dm_gattc_callback event = %d", event);
+
+ switch (event)
+ {
+ case BTA_GATTC_REG_EVT:
+ APPL_TRACE_DEBUG1("BTA_GATTC_REG_EVT client_if = %d", p_data->reg_oper.client_if);
+ if (p_data->reg_oper.status == BTA_GATT_OK)
+ bta_dm_search_cb.client_if = p_data->reg_oper.client_if;
+ else
+ bta_dm_search_cb.client_if = BTA_GATTS_INVALID_IF;
+ break;
+
+ case BTA_GATTC_OPEN_EVT:
+ bta_dm_proc_open_evt(&p_data->open);
+ break;
+
+ case BTA_GATTC_SEARCH_RES_EVT:
+ bta_dm_gatt_disc_result(p_data->srvc_res.service_uuid.id);
+ break;
+
+ case BTA_GATTC_SEARCH_CMPL_EVT:
+ if ( bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE)
+ bta_dm_gatt_disc_complete(p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
+ break;
+
+ case BTA_GATTC_CLOSE_EVT:
+ APPL_TRACE_DEBUG1("BTA_GATTC_CLOSE_EVT reason = %d", p_data->close.reason);
+ /* in case of disconnect before search is completed */
+ if ( (bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE) &&
+ !memcmp(p_data->close.remote_bda, bta_dm_search_cb.peer_bdaddr, BD_ADDR_LEN))
+ {
+ bta_dm_gatt_disc_complete((UINT16)BTA_GATT_INVALID_CONN_ID, (tBTA_GATT_STATUS) BTA_GATT_ERROR);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+#endif /* BTA_GATT_INCLUDED */
+
+#endif /* BLE_INCLUDED */
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
new file mode 100644
index 0000000..06e3b93
--- /dev/null
+++ b/bta/dm/bta_dm_api.c
@@ -0,0 +1,1616 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the API implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "bta_sys_int.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include <string.h>
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_dm_reg =
+{
+ bta_dm_sm_execute,
+ bta_dm_sm_disable
+};
+
+static const tBTA_SYS_REG bta_dm_search_reg =
+{
+ bta_dm_search_sm_execute,
+ bta_dm_search_sm_disable
+};
+
+/*******************************************************************************
+**
+** Function BTA_EnableBluetooth
+**
+** Description Enables bluetooth service. This function must be
+** called before any other functions in the BTA API are called.
+**
+**
+** Returns tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback)
+{
+
+ tBTA_DM_API_ENABLE *p_msg;
+
+ /* Bluetooth disabling is in progress */
+ if (bta_dm_cb.disabling)
+ return BTA_FAILURE;
+
+ memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+
+ GKI_sched_lock();
+ bta_sys_register (BTA_ID_DM, &bta_dm_reg );
+ bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );
+
+ /* if UUID list is not provided as static data */
+ bta_sys_eir_register(bta_dm_eir_update_uuid);
+
+ GKI_sched_unlock();
+
+ if ((p_msg = (tBTA_DM_API_ENABLE *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_ENABLE_EVT;
+ p_msg->p_sec_cback = p_cback;
+ bta_sys_sendmsg(p_msg);
+ return BTA_SUCCESS;
+ }
+ return BTA_FAILURE;
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DisableBluetooth
+**
+** Description Disables bluetooth service. This function is called when
+** the application no longer needs bluetooth service
+**
+** Returns void
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DisableBluetooth(void)
+{
+
+ BT_HDR *p_msg;
+
+ if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = BTA_DM_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+ else
+ {
+ return BTA_FAILURE;
+ }
+
+ return BTA_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function BTA_EnableTestMode
+**
+** Description Enables bluetooth device under test mode
+**
+**
+** Returns tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_EnableTestMode(void)
+{
+ BT_HDR *p_msg;
+
+ APPL_TRACE_API0("BTA_EnableTestMode");
+
+ if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = BTA_DM_API_ENABLE_TEST_MODE_EVT;
+ bta_sys_sendmsg(p_msg);
+ return BTA_SUCCESS;
+ }
+ return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function BTA_DisableTestMode
+**
+** Description Disable bluetooth device under test mode
+**
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_DisableTestMode(void)
+{
+ BT_HDR *p_msg;
+
+ APPL_TRACE_API0("BTA_DisableTestMode");
+
+ if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = BTA_DM_API_DISABLE_TEST_MODE_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmIsDeviceUp
+**
+** Description Called during startup to check whether the bluetooth module
+** is up and ready
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN BTA_DmIsDeviceUp(void)
+{
+
+ BOOLEAN status;
+
+ GKI_sched_lock();
+ status = BTM_IsDeviceUp();
+ GKI_sched_unlock();
+ return status;
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmSetDeviceName
+**
+** Description This function sets the Bluetooth name of local device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSetDeviceName(char *p_name)
+{
+
+ tBTA_DM_API_SET_NAME *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_SET_NAME *) GKI_getbuf(sizeof(tBTA_DM_API_SET_NAME))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_SET_NAME_EVT;
+ /* truncate the name if needed */
+ BCM_STRNCPY_S(p_msg->name, sizeof(p_msg->name), p_name, BD_NAME_LEN-1);
+ p_msg->name[BD_NAME_LEN-1]=0;
+
+ bta_sys_sendmsg(p_msg);
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmSetVisibility
+**
+** Description This function sets the Bluetooth connectable,
+** discoverable, pairable and conn paired only modes of local device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode, UINT8 pairable_mode, UINT8 conn_filter )
+{
+
+ tBTA_DM_API_SET_VISIBILITY *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_SET_VISIBILITY *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_SET_VISIBILITY_EVT;
+ p_msg->disc_mode = disc_mode;
+ p_msg->conn_mode = conn_mode;
+ p_msg->pair_mode = pairable_mode;
+ p_msg->conn_paired_only = conn_filter;
+
+
+ bta_sys_sendmsg(p_msg);
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmSetScanParam
+**
+** Description This function sets the parameters for page scan and
+** inquiry scan.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSetScanParam (UINT16 page_scan_interval, UINT16 page_scan_window,
+ UINT16 inquiry_scan_interval, UINT16 inquiry_scan_window)
+{
+ APPL_TRACE_API4 ("BTA_DmSetScanParam: %d, %d, %d, %d",
+ page_scan_interval, page_scan_window,
+ inquiry_scan_interval, inquiry_scan_window);
+
+ bta_dm_cb.page_scan_interval = page_scan_interval;
+ bta_dm_cb.page_scan_window = page_scan_window;
+ bta_dm_cb.inquiry_scan_interval = inquiry_scan_interval;
+ bta_dm_cb.inquiry_scan_window = inquiry_scan_window;
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmSetAfhChannels
+**
+** Description This function sets the AFH first and
+** last disable channel, so channels within
+** that range are disabled.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSetAfhChannels(UINT8 first, UINT8 last)
+{
+
+ tBTA_DM_API_SET_AFH_CHANNELS_EVT *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_SET_AFH_CHANNELS_EVT *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_SET_AFH_CHANNELS_EVT;
+ p_msg->first = first;
+ p_msg->last = last;
+ bta_sys_sendmsg(p_msg);
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_SetAfhChannelAssessment
+**
+** Description This function is called to set the channel assessment mode on or off
+**
+** Returns status
+**
+*******************************************************************************/
+void BTA_DmSetAfhChannelAssessment (BOOLEAN enable_or_disable)
+{
+ tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT *) GKI_getbuf(sizeof(tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_SET_AFH_CHANNEL_ASSESMENT_EVT;
+ p_msg->enable_or_disable = enable_or_disable;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmVendorSpecificCommand
+**
+** Description This function sends the vendor specific command
+** to the controller
+**
+**
+** Returns tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmVendorSpecificCommand (UINT16 opcode, UINT8 param_len,
+ UINT8 *p_param_buf,
+ tBTA_VENDOR_CMPL_CBACK *p_cback)
+{
+
+ tBTA_DM_API_VENDOR_SPECIFIC_COMMAND *p_msg;
+ UINT16 size;
+
+ /* If p_cback is NULL, Notify application */
+ if (p_cback == NULL)
+ {
+ return (BTA_FAILURE);
+ }
+ else
+ {
+ size = sizeof (tBTA_DM_API_VENDOR_SPECIFIC_COMMAND) + param_len;
+ if ((p_msg = (tBTA_DM_API_VENDOR_SPECIFIC_COMMAND *) GKI_getbuf(size)) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT;
+ p_msg->opcode = opcode;
+ p_msg->param_len = param_len;
+ p_msg->p_param_buf = (UINT8 *)(p_msg + 1);
+ p_msg->p_cback = p_cback;
+
+ memcpy (p_msg->p_param_buf, p_param_buf, param_len);
+
+ bta_sys_sendmsg(p_msg);
+ }
+ return (BTA_SUCCESS);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_DmSearch
+**
+** Description This function searches for peer Bluetooth devices. It performs
+** an inquiry and gets the remote name for devices. Service
+** discovery is done if services is non zero
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services, tBTA_DM_SEARCH_CBACK *p_cback)
+{
+
+ tBTA_DM_API_SEARCH *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(sizeof(tBTA_DM_API_SEARCH))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_SEARCH));
+
+ p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
+ memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
+ p_msg->services = services;
+ p_msg->p_cback = p_cback;
+ p_msg->rs_res = BTA_DM_RS_NONE;
+ bta_sys_sendmsg(p_msg);
+ }
+
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_DmSearchCancel
+**
+** Description This function cancels a search initiated by BTA_DmSearch
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSearchCancel(void)
+{
+ BT_HDR *p_msg;
+
+ if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = BTA_DM_API_SEARCH_CANCEL_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmDiscover
+**
+** Description This function does service discovery for services of a
+** peer device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmDiscover(BD_ADDR bd_addr, tBTA_SERVICE_MASK services,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+ tBTA_DM_API_DISCOVER *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_DISCOVER));
+
+ p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->services = services;
+ p_msg->p_cback = p_cback;
+ p_msg->sdp_search = sdp_search;
+ bta_sys_sendmsg(p_msg);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmDiscoverUUID
+**
+** Description This function does service discovery for services of a
+** peer device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmDiscoverUUID(BD_ADDR bd_addr, tSDP_UUID *uuid,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+ tBTA_DM_API_DISCOVER *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->services = BTA_USER_SERVICE_MASK; //Not exposed at API level
+ p_msg->p_cback = p_cback;
+ p_msg->sdp_search = sdp_search;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ p_msg->num_uuid = 0;
+ p_msg->p_uuid = NULL;
+#endif
+ memcpy( &p_msg->uuid, uuid, sizeof(tSDP_UUID) );
+ bta_sys_sendmsg(p_msg);
+ }
+
+}
+/*******************************************************************************
+**
+** Function BTA_DmIsMaster
+**
+** Description This function checks if the local device is the master of
+** the link to the given device
+**
+** Returns TRUE if master.
+** FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_DmIsMaster(BD_ADDR bd_addr)
+{
+ BOOLEAN is_master = FALSE;
+ UINT8 link_role;
+
+ BTM_GetRole(bd_addr, &link_role);
+ APPL_TRACE_API1("BTA_DmIsMaster role:x%x", link_role);
+ if(link_role == BTM_ROLE_MASTER)
+ {
+ is_master = TRUE;
+ }
+ return is_master;
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmBond
+**
+** Description This function initiates a bonding procedure with a peer
+** device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBond(BD_ADDR bd_addr)
+{
+ tBTA_DM_API_BOND *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_BOND *) GKI_getbuf(sizeof(tBTA_DM_API_BOND))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_BOND_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_msg);
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmBondCancel
+**
+** Description This function cancels the bonding procedure with a peer
+** device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBondCancel(BD_ADDR bd_addr)
+{
+ tBTA_DM_API_BOND_CANCEL *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_BOND_CANCEL *) GKI_getbuf(sizeof(tBTA_DM_API_BOND_CANCEL))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_BOND_CANCEL_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_msg);
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmPinReply
+**
+** Description This function provides a pincode for a remote device when
+** one is requested by DM through BTA_DM_PIN_REQ_EVT
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmPinReply(BD_ADDR bd_addr, BOOLEAN accept, UINT8 pin_len, UINT8 *p_pin)
+
+{
+ tBTA_DM_API_PIN_REPLY *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_PIN_REPLY *) GKI_getbuf(sizeof(tBTA_DM_API_PIN_REPLY))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_PIN_REPLY_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->accept = accept;
+ if(accept)
+ {
+ p_msg->pin_len = pin_len;
+ memcpy(p_msg->p_pin, p_pin, pin_len);
+ }
+ bta_sys_sendmsg(p_msg);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmLinkPolicy
+**
+** Description This function sets/clears the link policy mask to the given
+** bd_addr.
+** If clearing the sniff or park mode mask, the link is put
+** in active mode.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmLinkPolicy(BD_ADDR bd_addr, tBTA_DM_LP_MASK policy_mask,
+ BOOLEAN set)
+{
+ tBTA_DM_API_LINK_POLICY *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_LINK_POLICY *) GKI_getbuf(sizeof(tBTA_DM_API_LINK_POLICY))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_LINK_POLICY_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->policy_mask = policy_mask;
+ p_msg->set = set;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function BTA_DmLocalOob
+**
+** Description This function retrieves the OOB data from local controller.
+** The result is reported by bta_dm_co_loc_oob().
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmLocalOob(void)
+{
+ tBTA_DM_API_LOC_OOB *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_LOC_OOB *) GKI_getbuf(sizeof(tBTA_DM_API_LOC_OOB))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_LOC_OOB_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+#endif /* BTM_OOB_INCLUDED */
+/*******************************************************************************
+**
+** Function BTA_DmConfirm
+**
+** Description This function accepts or rejects the numerical value of the
+** Simple Pairing process on BTA_DM_SP_CFM_REQ_EVT
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmConfirm(BD_ADDR bd_addr, BOOLEAN accept)
+{
+ tBTA_DM_API_CONFIRM *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_CONFIRM *) GKI_getbuf(sizeof(tBTA_DM_API_CONFIRM))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_CONFIRM_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->accept = accept;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmPasskeyCancel
+**
+** Description This function is called to cancel the simple pairing process
+** reported by BTA_DM_SP_KEY_NOTIF_EVT
+**
+** Returns void
+**
+*******************************************************************************/
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+void BTA_DmPasskeyCancel(BD_ADDR bd_addr)
+{
+ tBTA_DM_API_PASKY_CANCEL *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_PASKY_CANCEL *) \
+ GKI_getbuf(sizeof(tBTA_DM_API_PASKY_CANCEL))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_PASKY_CANCEL_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_msg);
+ }
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function BTA_DmAddDevice
+**
+** Description This function adds a device to the security database list of
+** peer device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, LINK_KEY link_key,
+ tBTA_SERVICE_MASK trusted_mask, BOOLEAN is_trusted,
+ UINT8 key_type, tBTA_IO_CAP io_cap)
+{
+
+ tBTA_DM_API_ADD_DEVICE *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_ADD_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_DEVICE))) != NULL)
+ {
+ memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_DEVICE));
+
+ p_msg->hdr.event = BTA_DM_API_ADD_DEVICE_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->tm = trusted_mask;
+ p_msg->is_trusted = is_trusted;
+ p_msg->io_cap = io_cap;
+
+ if (link_key)
+ {
+ p_msg->link_key_known = TRUE;
+ p_msg->key_type = key_type;
+ memcpy(p_msg->link_key, link_key, LINK_KEY_LEN);
+ }
+
+ /* Load device class if specified */
+ if (dev_class)
+ {
+ p_msg->dc_known = TRUE;
+ memcpy (p_msg->dc, dev_class, DEV_CLASS_LEN);
+ }
+
+ memset (p_msg->bd_name, 0, BD_NAME_LEN);
+ memset (p_msg->features, 0, BD_FEATURES_LEN);
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_DmRemoveDevice
+**
+** Description This function removes a device fromthe security database list of
+** peer device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr)
+{
+ tBTA_DM_API_REMOVE_DEVICE *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_REMOVE_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_REMOVE_DEVICE))) != NULL)
+ {
+ memset (p_msg, 0, sizeof(tBTA_DM_API_REMOVE_DEVICE));
+
+ p_msg->hdr.event = BTA_DM_API_REMOVE_DEVICE_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_msg);
+ }
+ else
+ {
+ return BTA_FAILURE;
+ }
+
+ return BTA_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmAddDevWithName
+**
+** Description This function is newer version of BTA_DmAddDevice()
+** which added bd_name and features as input parameters.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmAddDevWithName (BD_ADDR bd_addr, DEV_CLASS dev_class,
+ BD_NAME bd_name, BD_FEATURES features,
+ LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
+ BOOLEAN is_trusted, UINT8 key_type, tBTA_IO_CAP io_cap)
+{
+ tBTA_DM_API_ADD_DEVICE *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_ADD_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_DEVICE))) != NULL)
+ {
+ memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_DEVICE));
+
+ p_msg->hdr.event = BTA_DM_API_ADD_DEVICE_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->tm = trusted_mask;
+ p_msg->is_trusted = is_trusted;
+ p_msg->io_cap = io_cap;
+
+ if (link_key)
+ {
+ p_msg->link_key_known = TRUE;
+ p_msg->key_type = key_type;
+ memcpy(p_msg->link_key, link_key, LINK_KEY_LEN);
+ }
+
+ /* Load device class if specified */
+ if (dev_class)
+ {
+ p_msg->dc_known = TRUE;
+ memcpy (p_msg->dc, dev_class, DEV_CLASS_LEN);
+ }
+
+ if (bd_name)
+ memcpy(p_msg->bd_name, bd_name, BD_NAME_LEN);
+
+ if (features)
+ memcpy(p_msg->features, features, BD_FEATURES_LEN);
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmAuthorizeReply
+**
+** Description This function provides an authorization reply when authorization
+** is requested by BTA through BTA_DM_AUTHORIZE_EVT
+**
+**
+** Returns tBTA_STATUS
+**
+*******************************************************************************/
+void BTA_DmAuthorizeReply(BD_ADDR bd_addr, tBTA_SERVICE_ID service, tBTA_AUTH_RESP response)
+{
+
+ tBTA_DM_API_AUTH_REPLY *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_AUTH_REPLY *) GKI_getbuf(sizeof(tBTA_DM_API_AUTH_REPLY))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_AUTH_REPLY_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->service = service;
+ p_msg->response = response;
+
+ bta_sys_sendmsg(p_msg);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmSignalStrength
+**
+** Description This function initiates RSSI and channnel quality
+** measurments. BTA_DM_SIG_STRENGTH_EVT is sent to
+** application with the values of RSSI and channel
+** quality
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSignalStrength(tBTA_SIG_STRENGTH_MASK mask, UINT16 period, BOOLEAN start)
+{
+
+ tBTA_API_DM_SIG_STRENGTH *p_msg;
+
+ if ((p_msg = (tBTA_API_DM_SIG_STRENGTH *) GKI_getbuf(sizeof(tBTA_API_DM_SIG_STRENGTH))) != NULL)
+ {
+ p_msg->hdr.event = BTA_API_DM_SIG_STRENGTH_EVT;
+ p_msg->mask = mask;
+ p_msg->period = period;
+ p_msg->start = start;
+
+ bta_sys_sendmsg(p_msg);
+ }
+
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmWriteInqTxPower
+**
+** Description This command is used to write the inquiry transmit power level
+** used to transmit the inquiry (ID) data packets.
+**
+** Parameters tx_power - tx inquiry power to use, valid value is -70 ~ 20
+
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmWriteInqTxPower(INT8 tx_power)
+{
+
+ tBTA_API_DM_TX_INQPWR *p_msg;
+
+ if ((p_msg = (tBTA_API_DM_TX_INQPWR *) GKI_getbuf(sizeof(tBTA_API_DM_TX_INQPWR))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_TX_INQPWR_EVT;
+ p_msg->tx_power = tx_power;
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_DmEirAddUUID
+**
+** Description This function is called to add UUID into EIR.
+**
+** Parameters tBT_UUID - UUID
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_DmEirAddUUID (tBT_UUID *p_uuid)
+{
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ tBTA_DM_API_UPDATE_EIR_UUID *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_UPDATE_EIR_UUID *) GKI_getbuf(sizeof(tBTA_DM_API_UPDATE_EIR_UUID))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_UPDATE_EIR_UUID_EVT;
+ p_msg->is_add = TRUE;
+ memcpy (&(p_msg->uuid), p_uuid, sizeof(tBT_UUID));
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmEirRemoveUUID
+**
+** Description This function is called to remove UUID from EIR.
+**
+** Parameters tBT_UUID - UUID
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_DmEirRemoveUUID (tBT_UUID *p_uuid)
+{
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ tBTA_DM_API_UPDATE_EIR_UUID *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_UPDATE_EIR_UUID *) GKI_getbuf(sizeof(tBTA_DM_API_UPDATE_EIR_UUID))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_UPDATE_EIR_UUID_EVT;
+ p_msg->is_add = FALSE;
+ memcpy (&(p_msg->uuid), p_uuid, sizeof(tBT_UUID));
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmSetEIRConfig
+**
+** Description This function is called to override the BTA default EIR parameters.
+** This funciton is only valid in a system where BTU & App task
+** are in the same memory space.
+**
+** Parameters Pointer to User defined EIR config
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_DmSetEIRConfig (tBTA_DM_EIR_CONF *p_eir_cfg)
+{
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+ tBTA_DM_API_SET_EIR_CONFIG *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_SET_EIR_CONFIG *) GKI_getbuf(sizeof(tBTA_DM_API_SET_EIR_CONFIG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_SET_EIR_CONFIG_EVT;
+ p_msg->p_eir_cfg = p_eir_cfg;
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_CheckEirData
+**
+** Description This function is called to get EIR data from significant part.
+**
+** Parameters p_eir - pointer of EIR significant part
+** type - finding EIR data type
+** p_length - return the length of EIR data
+**
+** Returns pointer of EIR data
+**
+*******************************************************************************/
+UINT8 *BTA_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
+{
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+ return BTM_CheckEirData( p_eir, type, p_length );
+#else
+ return NULL;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_GetEirService
+**
+** Description This function is called to get BTA service mask from EIR.
+**
+** Parameters p_eir - pointer of EIR significant part
+** p_services - return the BTA service mask
+**
+** Returns None
+**
+*******************************************************************************/
+extern const UINT16 bta_service_id_to_uuid_lkup_tbl [];
+void BTA_GetEirService( UINT8 *p_eir, tBTA_SERVICE_MASK *p_services )
+{
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+ UINT8 xx, yy;
+ UINT8 num_uuid, max_num_uuid = 32;
+ UINT8 uuid_list[32*LEN_UUID_16];
+ UINT16 *p_uuid16 = (UINT16 *)uuid_list;
+ tBTA_SERVICE_MASK mask;
+
+ BTM_GetEirUuidList( p_eir, LEN_UUID_16, &num_uuid, uuid_list, max_num_uuid);
+ for( xx = 0; xx < num_uuid; xx++ )
+ {
+ mask = 1;
+ for( yy = 0; yy < BTA_MAX_SERVICE_ID; yy++ )
+ {
+ if( *(p_uuid16 + xx) == bta_service_id_to_uuid_lkup_tbl[yy] )
+ {
+ *p_services |= mask;
+ break;
+ }
+ mask <<= 1;
+ }
+
+ /* for HSP v1.2 only device */
+ if (*(p_uuid16 + xx) == UUID_SERVCLASS_HEADSET_HS)
+ *p_services |= BTA_HSP_SERVICE_MASK;
+
+ if (*(p_uuid16 + xx) == UUID_SERVCLASS_HDP_SOURCE)
+ *p_services |= BTA_HL_SERVICE_MASK;
+
+ if (*(p_uuid16 + xx) == UUID_SERVCLASS_HDP_SINK)
+ *p_services |= BTA_HL_SERVICE_MASK;
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmUseSsr
+**
+** Description This function is called to check if the connected peer device
+** supports SSR or not.
+**
+** Returns TRUE, if SSR is supported
+**
+*******************************************************************************/
+BOOLEAN BTA_DmUseSsr( BD_ADDR bd_addr )
+{
+ BOOLEAN use_ssr = FALSE;
+ tBTA_DM_PEER_DEVICE * p_dev = bta_dm_find_peer_device(bd_addr);
+ if(p_dev && (p_dev->info & BTA_DM_DI_USE_SSR) )
+ use_ssr = TRUE;
+ return use_ssr;
+}
+
+/*******************************************************************************
+** Device Identification (DI) Server Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function BTA_DmSetLocalDiRecord
+**
+** Description This function adds a DI record to the local SDP database.
+**
+** Returns BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmSetLocalDiRecord( tBTA_DI_RECORD *p_device_info,
+ UINT32 *p_handle )
+{
+ tBTA_STATUS status = BTA_FAILURE;
+
+ if(bta_dm_di_cb.di_num < BTA_DI_NUM_MAX)
+ {
+ if(SDP_SetLocalDiRecord((tSDP_DI_RECORD *)p_device_info, p_handle) == SDP_SUCCESS)
+ {
+ if(!p_device_info->primary_record)
+ {
+ bta_dm_di_cb.di_handle[bta_dm_di_cb.di_num] = *p_handle;
+ bta_dm_di_cb.di_num ++;
+ }
+
+ bta_sys_add_uuid(UUID_SERVCLASS_PNP_INFORMATION);
+ status = BTA_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmGetLocalDiRecord
+**
+** Description Get a specified DI record to the local SDP database. If no
+** record handle is provided, the primary DI record will be
+** returned.
+**
+** Fills in the device information of the record
+** p_handle - if p_handle == 0, the primary record is returned
+**
+** Returns BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmGetLocalDiRecord( tBTA_DI_GET_RECORD *p_device_info,
+ UINT32 *p_handle )
+{
+ UINT16 status;
+
+ status = SDP_GetLocalDiRecord(p_device_info, p_handle);
+
+ if (status == SDP_SUCCESS)
+ return BTA_SUCCESS;
+ else
+ return BTA_FAILURE;
+
+}
+
+/*******************************************************************************
+** Device Identification (DI) Client Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function BTA_DmDiDiscover
+**
+** Description This function queries a remote device for DI information.
+**
+**
+** Returns None.
+**
+*******************************************************************************/
+void BTA_DmDiDiscover( BD_ADDR remote_device, tBTA_DISCOVERY_DB *p_db,
+ UINT32 len, tBTA_DM_SEARCH_CBACK *p_cback )
+{
+ tBTA_DM_API_DI_DISC *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_DI_DISC *) GKI_getbuf(sizeof(tBTA_DM_API_DI_DISC))) != NULL)
+ {
+ bdcpy(p_msg->bd_addr, remote_device);
+ p_msg->hdr.event = BTA_DM_API_DI_DISCOVER_EVT;
+ p_msg->p_sdp_db = p_db;
+ p_msg->len = len;
+ p_msg->p_cback = p_cback;
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmGetDiRecord
+**
+** Description This function retrieves a remote device's DI record from
+** the specified database.
+**
+** Returns BTA_SUCCESS if Get DI record is succeed.
+** BTA_FAILURE if Get DI record failed.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmGetDiRecord( UINT8 get_record_index, tBTA_DI_GET_RECORD *p_device_info,
+ tBTA_DISCOVERY_DB *p_db )
+{
+ if (SDP_GetDiRecord(get_record_index, p_device_info, p_db) != SDP_SUCCESS)
+ return BTA_FAILURE;
+ else
+ return BTA_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function BTA_SysFeatures
+**
+** Description This function is called to set system features.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_SysFeatures (UINT16 sys_features)
+{
+ bta_sys_cb.sys_features = sys_features;
+
+ APPL_TRACE_API1("BTA_SysFeatures: sys_features = %d", sys_features);
+}
+
+/*******************************************************************************
+**
+** Function bta_dmexecutecallback
+**
+** Description This function will request BTA to execute a call back in the context of BTU task
+** This API was named in lower case because it is only intended
+** for the internal customers(like BTIF).
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dmexecutecallback (tBTA_DM_EXEC_CBACK* p_callback, void * p_param)
+{
+ tBTA_DM_API_EXECUTE_CBACK *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_EXECUTE_CBACK *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_API_EXECUTE_CBACK_EVT;
+ p_msg->p_param= p_param;
+ p_msg->p_exec_cback= p_callback;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmAddBleKey
+**
+** Description Add/modify LE device information. This function will be
+** normally called during host startup to restore all required
+** information stored in the NVRAM.
+**
+** Parameters: bd_addr - BD address of the peer
+** p_le_key - LE key values.
+** key_type - LE SMP key type.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmAddBleKey (BD_ADDR bd_addr, tBTA_LE_KEY_VALUE *p_le_key, tBTA_LE_KEY_TYPE key_type)
+{
+#if BLE_INCLUDED == TRUE
+
+ tBTA_DM_API_ADD_BLEKEY *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_ADD_BLEKEY *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_BLEKEY))) != NULL)
+ {
+ memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_BLEKEY));
+
+ p_msg->hdr.event = BTA_DM_API_ADD_BLEKEY_EVT;
+ p_msg->key_type = key_type;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ memcpy(&p_msg->blekey, p_le_key, sizeof(tBTA_LE_KEY_VALUE));
+
+ bta_sys_sendmsg(p_msg);
+ }
+
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmAddBleDevice
+**
+** Description Add a BLE device. This function will be normally called
+** during host startup to restore all required information
+** for a LE device stored in the NVRAM.
+**
+** Parameters: bd_addr - BD address of the peer
+** dev_type - Remote device's device type.
+** addr_type - LE device address type.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmAddBleDevice(BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type, tBT_DEVICE_TYPE dev_type)
+{
+#if BLE_INCLUDED == TRUE
+ tBTA_DM_API_ADD_BLE_DEVICE *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_ADD_BLE_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_BLE_DEVICE))) != NULL)
+ {
+ memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_BLE_DEVICE));
+
+ p_msg->hdr.event = BTA_DM_API_ADD_BLEDEVICE_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->addr_type = addr_type;
+ p_msg->dev_type = dev_type;
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+/*******************************************************************************
+**
+** Function BTA_DmBlePasskeyReply
+**
+** Description Send BLE SMP passkey reply.
+**
+** Parameters: bd_addr - BD address of the peer
+** accept - passkey entry sucessful or declined.
+** passkey - passkey value, must be a 6 digit number,
+** can be lead by 0.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passkey)
+{
+#if BLE_INCLUDED == TRUE
+ tBTA_DM_API_PASSKEY_REPLY *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_PASSKEY_REPLY *) GKI_getbuf(sizeof(tBTA_DM_API_PASSKEY_REPLY))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_PASSKEY_REPLY));
+
+ p_msg->hdr.event = BTA_DM_API_BLE_PASSKEY_REPLY_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->accept = accept;
+
+ if(accept)
+ {
+ p_msg->passkey = passkey;
+ }
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+/*******************************************************************************
+**
+** Function BTA_DmBleSecurityGrant
+**
+** Description Grant security request access.
+**
+** Parameters: bd_addr - BD address of the peer
+** res - security grant status.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBleSecurityGrant(BD_ADDR bd_addr, tBTA_DM_BLE_SEC_GRANT res)
+{
+#if BLE_INCLUDED == TRUE
+ tBTA_DM_API_BLE_SEC_GRANT *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_BLE_SEC_GRANT *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_SEC_GRANT))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SEC_GRANT));
+
+ p_msg->hdr.event = BTA_DM_API_BLE_SEC_GRANT_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->res = res;
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+/*******************************************************************************
+**
+** Function BTA_DmSetBlePrefConnParams
+**
+** Description This function is called to set the preferred connection
+** parameters when default connection parameter is not desired.
+**
+** Parameters: bd_addr - BD address of the peripheral
+** scan_interval - scan interval
+** scan_window - scan window
+** min_conn_int - minimum preferred connection interval
+** max_conn_int - maximum preferred connection interval
+** slave_latency - preferred slave latency
+** supervision_tout - preferred supervision timeout
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr,
+ UINT16 min_conn_int, UINT16 max_conn_int,
+ UINT16 slave_latency, UINT16 supervision_tout )
+{
+#if BLE_INCLUDED == TRUE
+ tBTA_DM_API_BLE_CONN_PARAMS *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_BLE_CONN_PARAMS *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_CONN_PARAMS))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_CONN_PARAMS));
+
+ p_msg->hdr.event = BTA_DM_API_BLE_CONN_PARAM_EVT;
+
+ memcpy(p_msg->peer_bda, bd_addr, BD_ADDR_LEN);
+
+ p_msg->conn_int_max = max_conn_int;
+ p_msg->conn_int_min = min_conn_int;
+ p_msg->slave_latency = slave_latency;
+ p_msg->supervision_tout = supervision_tout;
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmSetBleConnScanParams
+**
+** Description This function is called to set scan parameters used in
+** BLE connection request
+**
+** Parameters: scan_interval - scan interval
+** scan_window - scan window
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSetBleConnScanParams(UINT16 scan_interval, UINT16 scan_window )
+{
+#if BLE_INCLUDED == TRUE
+ tBTA_DM_API_BLE_SCAN_PARAMS *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_BLE_SCAN_PARAMS *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_SCAN_PARAMS))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SCAN_PARAMS));
+
+ p_msg->hdr.event = BTA_DM_API_BLE_SCAN_PARAM_EVT;
+
+ p_msg->scan_int = scan_interval;
+ p_msg->scan_window = scan_window;
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmBleSetBgConnType
+**
+** Description This function is called to set BLE connectable mode for a
+** peripheral device.
+**
+** Parameters bg_conn_type: it can be auto connection, or selective connection.
+** p_select_cback: callback function when selective connection procedure
+** is being used.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmBleSetBgConnType(tBTA_DM_BLE_CONN_TYPE bg_conn_type, tBTA_DM_BLE_SEL_CBACK *p_select_cback)
+{
+#if BLE_INCLUDED == TRUE
+ tBTA_DM_API_BLE_SET_BG_CONN_TYPE *p_msg;
+
+ if ((p_msg = (tBTA_DM_API_BLE_SET_BG_CONN_TYPE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_SET_BG_CONN_TYPE))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SET_BG_CONN_TYPE));
+
+ p_msg->hdr.event = BTA_DM_API_BLE_SET_BG_CONN_TYPE;
+ p_msg->bg_conn_type = bg_conn_type;
+ p_msg->p_select_cback = p_select_cback;
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+/*******************************************************************************
+**
+** Function BTA_DmDiscoverExt
+**
+** Description This function does service discovery for services of a
+** peer device. When services.num_uuid is 0, it indicates all
+** GATT based services are to be searched; other wise a list of
+** UUID of interested services should be provided through
+** p_services->p_uuid.
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ tBTA_DM_API_DISCOVER *p_msg;
+ UINT16 len = p_services ? (sizeof(tBTA_DM_API_DISCOVER) + sizeof(tBT_UUID) * p_services->num_uuid) :
+ sizeof(tBTA_DM_API_DISCOVER);
+
+ if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_msg, 0, len);
+
+ p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->p_cback = p_cback;
+ p_msg->sdp_search = sdp_search;
+
+ if (p_services != NULL)
+ {
+ p_msg->services = p_services->srvc_mask;
+ p_msg->num_uuid = p_services->num_uuid;
+
+ if (p_services->num_uuid != 0)
+ {
+ p_msg->p_uuid = (tBT_UUID *)(p_msg + 1);
+ memcpy(p_msg->p_uuid, p_services->p_uuid, sizeof(tBT_UUID) * p_services->num_uuid);
+ }
+ }
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmSearchExt
+**
+** Description This function searches for peer Bluetooth devices. It performs
+** an inquiry and gets the remote name for devices. Service
+** discovery is done if services is non zero
+**
+** Parameters p_dm_inq: inquiry conditions
+** p_services: if service is not empty, service discovery will be done.
+** for all GATT based service condition, put num_uuid, and
+** p_uuid is the pointer to the list of UUID values.
+** p_cback: callback functino when search is completed.
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSearchExt(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK_EXT *p_services, tBTA_DM_SEARCH_CBACK *p_cback)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ tBTA_DM_API_SEARCH *p_msg;
+ UINT16 len = p_services ? (sizeof(tBTA_DM_API_SEARCH) + sizeof(tBT_UUID) * p_services->num_uuid) :
+ sizeof(tBTA_DM_API_SEARCH);
+
+ if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_msg, 0, len);
+
+ p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
+ memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
+ p_msg->p_cback = p_cback;
+ p_msg->rs_res = BTA_DM_RS_NONE;
+
+
+ if (p_services != NULL)
+ {
+ p_msg->services = p_services->srvc_mask;
+ p_msg->num_uuid = p_services->num_uuid;
+
+ if (p_services->num_uuid != 0)
+ {
+ p_msg->p_uuid = (tBT_UUID *)(p_msg + 1);
+ memcpy(p_msg->p_uuid, p_services->p_uuid, sizeof(tBT_UUID) * p_services->num_uuid);
+ }
+ else
+ p_msg->p_uuid = NULL;
+ }
+
+ bta_sys_sendmsg(p_msg);
+ }
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_DmSetEncryption
+**
+** Description This function is called to ensure that connection is
+** encrypted. Should be called only on an open connection.
+** Typically only needed for connections that first want to
+** bring up unencrypted links, then later encrypt them.
+**
+** Parameters: bd_addr - Address of the peer device
+** p_callback - Pointer to callback function to indicat the
+** link encryption status
+** sec_act - This is the security action to indicate
+** what knid of BLE security level is required for
+** the BLE link if the BLE is supported
+** Note: This parameter is ignored for the BR/EDR link
+** or the BLE is not supported
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
+ tBTA_DM_BLE_SEC_ACT sec_act)
+{
+ tBTA_DM_API_SET_ENCRYPTION *p_msg;
+
+ APPL_TRACE_API0("BTA_DmSetEncryption"); //todo
+ if ((p_msg = (tBTA_DM_API_SET_ENCRYPTION *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ENCRYPTION))) != NULL)
+ {
+ memset(p_msg, 0, sizeof(tBTA_DM_API_SET_ENCRYPTION));
+
+ p_msg->hdr.event = BTA_DM_API_SET_ENCRYPTION_EVT;
+
+ memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
+ p_msg->p_callback = p_callback;
+ p_msg->sec_act = sec_act;
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
new file mode 100644
index 0000000..5e26909
--- /dev/null
+++ b/bta/dm/bta_dm_cfg.c
@@ -0,0 +1,424 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains compile-time configurable constants for the device
+ * manager.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+
+#ifndef BTA_DM_LINK_POLICY_SETTINGS
+#define BTA_DM_LINK_POLICY_SETTINGS (HCI_ENABLE_MASTER_SLAVE_SWITCH | HCI_ENABLE_HOLD_MODE | HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE)
+#endif
+
+/* page timeout in 625uS */
+#ifndef BTA_DM_PAGE_TIMEOUT
+#define BTA_DM_PAGE_TIMEOUT 8192
+#endif
+
+/* link supervision timeout in 625uS (5 secs) */
+#ifndef BTA_DM_LINK_TIMEOUT
+#define BTA_DM_LINK_TIMEOUT 8000
+#endif
+
+/* For Insight, PM cfg lookup tables are runtime configurable (to allow tweaking of params for power consumption measurements) */
+#ifndef BTE_SIM_APP
+#define tBTA_DM_PM_TYPE_QUALIFIER const
+#else
+#define tBTA_DM_PM_TYPE_QUALIFIER
+#endif
+
+
+const tBTA_DM_CFG bta_dm_cfg =
+{
+ /* mobile phone COD */
+ BTA_DM_COD,
+ /* link policy settings */
+ BTA_DM_LINK_POLICY_SETTINGS,
+ /* page timeout in 625uS */
+ BTA_DM_PAGE_TIMEOUT,
+ /* link supervision timeout in 625uS*/
+ BTA_DM_LINK_TIMEOUT,
+ /* TRUE to avoid scatternet when av is streaming (be the master) */
+ TRUE
+};
+
+#ifndef BTA_DM_SCATTERNET
+/* By default, allow partial scatternet */
+#define BTA_DM_SCATTERNET BTA_DM_PARTIAL_SCATTERNET
+#endif
+
+#ifndef BTA_HH_ROLE
+/* By default, do not specify HH role (backward compatibility) */
+#define BTA_HH_ROLE BTA_ANY_ROLE
+#endif
+
+#ifndef BTA_AV_ROLE
+/* By default, AV role (backward BTA_MASTER_ROLE_PREF) */
+#define BTA_AV_ROLE BTA_MASTER_ROLE_PREF
+#endif
+
+#define BTA_DM_NUM_RM_ENTRY 4
+
+/* appids for PAN used by insight sample application
+ these have to be same as defined in btui_int.h */
+#define BTUI_PAN_ID_PANU 0
+#define BTUI_PAN_ID_NAP 1
+#define BTUI_PAN_ID_GN 2
+
+/* First element is always for SYS:
+ app_id = # of entries table, cfg is
+ device scatternet support */
+const tBTA_DM_RM bta_dm_rm_cfg[] =
+{
+ {BTA_ID_SYS, BTA_DM_NUM_RM_ENTRY, BTA_DM_SCATTERNET},
+ {BTA_ID_PAN, BTUI_PAN_ID_NAP, BTA_MASTER_ROLE_ONLY},
+ {BTA_ID_PAN, BTUI_PAN_ID_GN, BTA_MASTER_ROLE_ONLY},
+ {BTA_ID_HH, BTA_ALL_APP_ID, BTA_HH_ROLE},
+ {BTA_ID_AV, BTA_ALL_APP_ID, BTA_AV_ROLE}
+};
+
+
+tBTA_DM_CFG *p_bta_dm_cfg = (tBTA_DM_CFG *)&bta_dm_cfg;
+
+tBTA_DM_RM *p_bta_dm_rm_cfg = (tBTA_DM_RM *)&bta_dm_rm_cfg;
+
+
+#define BTA_DM_NUM_PM_ENTRY (15+BTA_DM_NUM_JV_ID) /* number of entries in bta_dm_pm_cfg except the first */
+
+tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[] =
+{
+ {BTA_ID_SYS, BTA_DM_NUM_PM_ENTRY, 0},
+ {BTA_ID_AG, BTA_ALL_APP_ID, 0}, /* ag uses first spec table for app id 0 */
+ {BTA_ID_CT, 1, 1}, /* ct (BTA_ID_CT,APP ID=1) spec table */
+ {BTA_ID_CG, BTA_ALL_APP_ID, 1}, /* cg resue ct spec table */
+ {BTA_ID_DG, BTA_ALL_APP_ID, 2}, /* dg spec table */
+ {BTA_ID_AV, BTA_ALL_APP_ID, 4}, /* av spec table */
+ {BTA_ID_FTC, BTA_ALL_APP_ID, 6}, /* ftc spec table */
+ {BTA_ID_FTS, BTA_ALL_APP_ID, 7}, /* fts spec table */
+ {BTA_ID_HD, BTA_ALL_APP_ID, 3}, /* hd spec table */
+ {BTA_ID_HH, BTA_ALL_APP_ID, 5}, /* hh spec table */
+ {BTA_ID_PBC, BTA_ALL_APP_ID, 2}, /* reuse dg spec table */
+ {BTA_ID_PBS, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
+ {BTA_ID_OPC, BTA_ALL_APP_ID, 6}, /* reuse ftc spec table */
+ {BTA_ID_OPS, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
+ {BTA_ID_MSE, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
+ {BTA_ID_JV1, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
+ {BTA_ID_JV2, BTA_ALL_APP_ID, 7}, /* reuse fts spec table */
+ {BTA_ID_HL, BTA_ALL_APP_ID, 8} /* reuse fts spec table */
+};
+
+
+#ifdef BTE_SIM_APP /* For Insight builds only, see the detail below */
+#define BTA_DM_NUM_PM_SPEC (9 + 2) /* additional two */
+#else
+#define BTA_DM_NUM_PM_SPEC 9 /* additional JV*/
+#endif
+
+tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] =
+{
+ /* AG */
+ {
+ (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR2), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_SNIFF3, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */
+ {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_RETRY, 5000}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ },
+
+ /* CT */
+ {
+ (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR2), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_PARK, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open park */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open sniff */
+ {{BTA_DM_PM_PARK, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close park */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_RETRY, 5000}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ },
+
+ /* DG */
+ {
+ (BTA_DM_PM_ACTIVE), /* no power saving mode allowed */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR2), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ },
+
+ /* HD */
+ {
+ (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR3), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_SNIFF4, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
+ {{BTA_DM_PM_SNIFF2, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF4, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ },
+
+ /* AV */
+ {
+ (BTA_DM_PM_SNIFF), /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR2), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
+ {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ },
+
+ /* HH */
+ {
+ (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR1), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_SNIFF2, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close, used for HH suspend */
+ {{BTA_DM_PM_SNIFF2, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_SNIFF2, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ },
+
+ /* FTC, OPC */
+ {
+ (BTA_DM_PM_SNIFF), /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR2), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
+ {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ },
+
+ /* FTS, OPS */
+ {
+ (BTA_DM_PM_SNIFF), /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR2), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open active */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
+ {{BTA_DM_PM_SNIFF, 7000}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ },
+
+ /* HL */
+ {
+ (BTA_DM_PM_SNIFF), /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+ (BTA_DM_PM_SSR2), /* the SSR entry */
+#endif
+ {
+ {{BTA_DM_PM_SNIFF, 5000}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
+ {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open, active */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close sniff */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+ {{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+ {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+ }
+ }
+
+#ifdef BTE_SIM_APP /* For Insight builds only */
+ /* Entries at the end of the pm_spec table are user-defined (runtime configurable),
+ for power consumption experiments.
+ Insight finds the first user-defined entry by looking for the first BTA_DM_PM_NO_PREF.
+ The number of user_defined specs is defined by BTA_SWRAP_UD_PM_SPEC_COUNT */
+ ,
+ {BTA_DM_PM_NO_PREF}, /* pm_spec USER_DEFINED_0 */
+ {BTA_DM_PM_NO_PREF} /* pm_spec USER_DEFINED_1 */
+#endif /* BTE_SIM_APP */
+};
+
+tBTA_DM_PM_TYPE_QUALIFIER tBTM_PM_PWR_MD bta_dm_pm_md[] =
+{
+/* more sniff parameter entries can be added for BTA_DM_PM_SNIFF3 - BTA_DM_PM_SNIFF7, if needed
+When entries are added or removed, BTA_DM_PM_PARK_IDX needs to be updated to reflect the actual index
+BTA_DM_PM_PARK_IDX is defined in bta_api.h and can be override by the bdroid_buildcfg.h settings.
+The SNIFF table entries must be in the order from highest latency (biggest interval) to lowest latency.
+If there's a conflict among the connected services, the setting with lowest latency wins.
+*/
+/* sniff modes: max interval, min interval, attempt, timeout */
+ {800, 400, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF - A2DP */
+ {400, 200, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF1 */
+ {180, 150, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF2- HD idle */
+ {150, 50, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF3- SCO open */
+ { 54, 30, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF4- HD active*/
+ {800, 400, 0, 0, BTM_PM_MD_PARK}
+
+#ifdef BTE_SIM_APP /* For Insight builds only */
+ /* Entries at the end of the bta_dm_pm_md table are user-defined (runtime configurable),
+ for power consumption experiments.
+ Insight finds the first user-defined entry by looking for the first 'max=0'.
+ The number of user_defined specs is defined by BTA_SWRAP_UD_PM_DM_COUNT */
+ ,
+ {0}, /* CONN_OPEN/SCO_CLOSE power mode settings for pm_spec USER_DEFINED_0 */
+ {0}, /* SCO_OPEN power mode settings for pm_spec USER_DEFINED_0 */
+
+ {0}, /* CONN_OPEN/SCO_CLOSE power mode settings for pm_spec USER_DEFINED_1 */
+ {0} /* SCO_OPEN power mode settings for pm_spec USER_DEFINED_1 */
+#endif /* BTE_SIM_APP */
+};
+
+/* 0=max_lat -> no SSR */
+/* the smaller of the SSR max latency wins.
+ * the entries in this table must be from highest latency (biggest interval) to lowest latency */
+#if (BTM_SSR_INCLUDED == TRUE)
+tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] =
+{
+ /*max_lat, min_rmt_to, min_loc_to*/
+ {0, 0, 0}, /* BTA_DM_PM_SSR0 - do not use SSR */
+ {1600, 2, 2}, /* BTA_DM_PM_SSR1 - HH */
+ {1200, 2, 2}, /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
+ {360, 160, 2} /* BTA_DM_PM_SSR3 - HD */
+};
+
+tBTA_DM_SSR_SPEC *p_bta_dm_ssr_spec = (tBTA_DM_SSR_SPEC *)&bta_dm_ssr_spec;
+#endif
+
+tBTA_DM_PM_CFG *p_bta_dm_pm_cfg = (tBTA_DM_PM_CFG *)&bta_dm_pm_cfg;
+tBTA_DM_PM_SPEC *p_bta_dm_pm_spec = (tBTA_DM_PM_SPEC *)&bta_dm_pm_spec;
+tBTM_PM_PWR_MD *p_bta_dm_pm_md = (tBTM_PM_PWR_MD *)&bta_dm_pm_md;
+
+/* The performance impact of EIR packet size
+**
+** When BTM_EIR_DEFAULT_FEC_REQUIRED is TRUE,
+** 1 to 17 bytes, DM1 is used and most robust.
+** 18 to 121 bytes, DM3 is used but impacts inquiry scan time with large number
+** of devices.(almost double with 150 users)
+** 122 to 224 bytes, DM5 is used but cause quite big performance loss even with
+** small number of users. so it is not recommended.
+** 225 to 240 bytes, DH5 is used without FEC but it not recommended.
+** (same reason of DM5)
+**
+** When BTM_EIR_DEFAULT_FEC_REQUIRED is FALSE,
+** 1 to 27 bytes, DH1 is used but only robust at short range.
+** 28 to 183 bytes, DH3 is used but only robust at short range and impacts inquiry
+** scan time with large number of devices.
+** 184 to 240 bytes, DH5 is used but it not recommended.
+*/
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+ /* for example */
+const UINT8 bta_dm_eir_uuid16_list[] = { 0x08, 0x11, /* Headset */
+ 0x1E, 0x11, /* Handsfree */
+ 0x0E, 0x11, /* AV Remote Control */
+ 0x0B, 0x11, /* Audio Sink */
+};
+#endif
+
+/* Extended Inquiry Response */
+const tBTA_DM_EIR_CONF bta_dm_eir_cfg =
+{
+ 50, /* minimum length of local name when it is shortened */
+ /* if length of local name is longer than this and EIR has not enough */
+ /* room for all UUID list then local name is shortened to this length */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+ 8,
+ (UINT8 *)bta_dm_eir_uuid16_list,
+#else
+ { /* mask of UUID list in EIR */
+ 0xFFFFFFFF, /* LSB is the first UUID of the first 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */
+ 0xFFFFFFFF /* LSB is the first UUID of the next 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */
+ /* BTM_EIR_UUID_LKUP_TBL can be overrided */
+ },
+#endif
+ NULL, /* Inquiry TX power */
+ 0, /* length of flags in bytes */
+ NULL, /* flags for EIR */
+ 0, /* length of manufacturer specific in bytes */
+ NULL, /* manufacturer specific */
+};
+tBTA_DM_EIR_CONF *p_bta_dm_eir_cfg = (tBTA_DM_EIR_CONF*)&bta_dm_eir_cfg;
+#endif
diff --git a/bta/dm/bta_dm_ci.c b/bta/dm/bta_dm_ci.c
new file mode 100644
index 0000000..5e2e312
--- /dev/null
+++ b/bta/dm/bta_dm_ci.c
@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the API implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include <string.h>
+#include "bta_dm_ci.h"
+
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function bta_dm_ci_io_req
+**
+** Description This function must be called in response to function
+** bta_dm_co_io_req(), if *p_oob_data to BTA_OOB_UNKNOWN
+** by bta_dm_co_io_req().
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_ci_io_req(BD_ADDR bd_addr, tBTA_IO_CAP io_cap, tBTA_OOB_DATA oob_data,
+ tBTA_AUTH_REQ auth_req)
+
+{
+ tBTA_DM_CI_IO_REQ *p_msg;
+
+ if ((p_msg = (tBTA_DM_CI_IO_REQ *) GKI_getbuf(sizeof(tBTA_DM_CI_IO_REQ))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_CI_IO_REQ_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->io_cap = io_cap;
+ p_msg->oob_data = oob_data;
+ p_msg->auth_req = auth_req;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_ci_rmt_oob
+**
+** Description This function must be called in response to function
+** bta_dm_co_rmt_oob() to provide the OOB data associated
+** with the remote device.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 r)
+{
+ tBTA_DM_CI_RMT_OOB *p_msg;
+
+ if ((p_msg = (tBTA_DM_CI_RMT_OOB *) GKI_getbuf(sizeof(tBTA_DM_CI_RMT_OOB))) != NULL)
+ {
+ p_msg->hdr.event = BTA_DM_CI_RMT_OOB_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->accept = accept;
+ memcpy(p_msg->c, c, BT_OCTET16_LEN);
+ memcpy(p_msg->r, r, BT_OCTET16_LEN);
+ bta_sys_sendmsg(p_msg);
+ }
+}
+#endif /* BTM_OOB_INCLUDED */
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function bta_dm_sco_ci_data_ready
+**
+** Description This function sends an event to indicating that the phone
+** has SCO data ready.
+**
+** Parameters event: is obtained from bta_dm_sco_co_open() function, which
+** is the BTA event we want to send back to BTA module
+** when there is encoded data ready.
+** sco_handle: is the BTA sco handle which indicate a specific
+** SCO connection.
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = event;
+ p_buf->layer_specific = sco_handle;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+#endif
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
new file mode 100644
index 0000000..35b369d
--- /dev/null
+++ b/bta/dm/bta_dm_int.h
@@ -0,0 +1,989 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private interface file for the BTA device manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_INT_H
+#define BTA_DM_INT_H
+
+#include "bt_target.h"
+
+#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+ #include "bta_gatt_api.h"
+#endif
+
+
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+
+#define BTA_COPY_DEVICE_CLASS(coddst, codsrc) {((UINT8 *)(coddst))[0] = ((UINT8 *)(codsrc))[0]; \
+ ((UINT8 *)(coddst))[1] = ((UINT8 *)(codsrc))[1]; \
+ ((UINT8 *)(coddst))[2] = ((UINT8 *)(codsrc))[2];}
+
+
+#define BTA_DM_MSG_LEN 50
+
+#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id))
+
+/* DM events */
+enum
+{
+ /* device manager local device API events */
+ BTA_DM_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_DM),
+ BTA_DM_API_DISABLE_EVT,
+ BTA_DM_API_SET_NAME_EVT,
+ BTA_DM_API_SET_VISIBILITY_EVT,
+ BTA_DM_API_SET_AFH_CHANNELS_EVT,
+ BTA_API_DM_SIG_STRENGTH_EVT,
+ BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT,
+ BTA_DM_API_TX_INQPWR_EVT,
+ BTA_DM_ACL_CHANGE_EVT,
+ BTA_DM_API_ADD_DEVICE_EVT,
+
+ /* security API events */
+ BTA_DM_API_BOND_EVT,
+ BTA_DM_API_BOND_CANCEL_EVT,
+ BTA_DM_API_PIN_REPLY_EVT,
+ BTA_DM_API_LINK_POLICY_EVT,
+ BTA_DM_API_AUTH_REPLY_EVT,
+
+ /* power manger events */
+ BTA_DM_PM_BTM_STATUS_EVT,
+ BTA_DM_PM_TIMER_EVT,
+
+ /* simple pairing events */
+ BTA_DM_API_CONFIRM_EVT,
+
+ BTA_DM_API_SET_ENCRYPTION_EVT,
+
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+ BTA_DM_API_PASKY_CANCEL_EVT,
+#endif
+#if (BTM_OOB_INCLUDED == TRUE)
+ BTA_DM_API_LOC_OOB_EVT,
+ BTA_DM_CI_IO_REQ_EVT,
+ BTA_DM_CI_RMT_OOB_EVT,
+#endif /* BTM_OOB_INCLUDED */
+
+ BTA_DM_API_REMOVE_DEVICE_EVT,
+
+#if BLE_INCLUDED == TRUE
+ BTA_DM_API_ADD_BLEKEY_EVT,
+ BTA_DM_API_ADD_BLEDEVICE_EVT,
+ BTA_DM_API_BLE_PASSKEY_REPLY_EVT,
+ BTA_DM_API_BLE_SEC_GRANT_EVT,
+ BTA_DM_API_BLE_SET_BG_CONN_TYPE,
+ BTA_DM_API_BLE_CONN_PARAM_EVT,
+ BTA_DM_API_BLE_SCAN_PARAM_EVT,
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ BTA_DM_API_UPDATE_EIR_UUID_EVT,
+#endif
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+ BTA_DM_API_SET_EIR_CONFIG_EVT,
+#endif
+
+ BTA_DM_API_ENABLE_TEST_MODE_EVT,
+ BTA_DM_API_DISABLE_TEST_MODE_EVT,
+ BTA_DM_API_EXECUTE_CBACK_EVT,
+ BTA_DM_API_SET_AFH_CHANNEL_ASSESMENT_EVT,
+ BTA_DM_MAX_EVT
+};
+
+
+/* DM search events */
+enum
+{
+ /* DM search API events */
+ BTA_DM_API_SEARCH_EVT = BTA_SYS_EVT_START(BTA_ID_DM_SEARCH),
+ BTA_DM_API_SEARCH_CANCEL_EVT,
+ BTA_DM_API_DISCOVER_EVT,
+ BTA_DM_INQUIRY_CMPL_EVT,
+ BTA_DM_REMT_NAME_EVT,
+ BTA_DM_SDP_RESULT_EVT,
+ BTA_DM_SEARCH_CMPL_EVT,
+ BTA_DM_DISCOVERY_RESULT_EVT,
+ BTA_DM_API_DI_DISCOVER_EVT
+
+};
+
+/* data type for BTA_DM_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_SEC_CBACK *p_sec_cback;
+} tBTA_DM_API_ENABLE;
+
+/* data type for BTA_DM_API_SET_NAME_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char name[BD_NAME_LEN];
+} tBTA_DM_API_SET_NAME;
+
+/* data type for BTA_DM_API_SET_VISIBILITY_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_DISC disc_mode;
+ tBTA_DM_CONN conn_mode;
+ UINT8 pair_mode;
+ UINT8 conn_paired_only;
+} tBTA_DM_API_SET_VISIBILITY;
+
+/* data type for BTA_DM_API_SET_AFH_CHANNELS_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 first;
+ UINT8 last;
+} tBTA_DM_API_SET_AFH_CHANNELS_EVT;
+
+/* data type for BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 opcode;
+ UINT8 param_len;
+ UINT8 *p_param_buf;
+ tBTA_VENDOR_CMPL_CBACK *p_cback;
+
+} tBTA_DM_API_VENDOR_SPECIFIC_COMMAND;
+
+enum
+{
+ BTA_DM_RS_NONE, /* straight API call */
+ BTA_DM_RS_OK, /* the role switch result - successful */
+ BTA_DM_RS_FAIL /* the role switch result - failed */
+};
+typedef UINT8 tBTA_DM_RS_RES;
+
+/* data type for BTA_DM_API_SEARCH_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_INQ inq_params;
+ tBTA_SERVICE_MASK services;
+ tBTA_DM_SEARCH_CBACK * p_cback;
+ tBTA_DM_RS_RES rs_res;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ UINT8 num_uuid;
+ tBT_UUID *p_uuid;
+#endif
+} tBTA_DM_API_SEARCH;
+
+/* data type for BTA_DM_API_DISCOVER_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_SERVICE_MASK services;
+ tBTA_DM_SEARCH_CBACK * p_cback;
+ BOOLEAN sdp_search;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+ UINT8 num_uuid;
+ tBT_UUID *p_uuid;
+#endif
+ tSDP_UUID uuid;
+} tBTA_DM_API_DISCOVER;
+
+/* data type for BTA_DM_API_DI_DISC_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_DISCOVERY_DB *p_sdp_db;
+ UINT32 len;
+ tBTA_DM_SEARCH_CBACK * p_cback;
+}tBTA_DM_API_DI_DISC;
+
+/* data type for BTA_DM_API_BOND_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_DM_API_BOND;
+
+/* data type for BTA_DM_API_BOND_CANCEL_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_DM_API_BOND_CANCEL;
+
+/* data type for BTA_DM_API_PIN_REPLY_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ BOOLEAN accept;
+ UINT8 pin_len;
+ UINT8 p_pin[PIN_CODE_LEN];
+} tBTA_DM_API_PIN_REPLY;
+
+/* data type for BTA_DM_API_LINK_POLICY_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ UINT16 policy_mask;
+ BOOLEAN set;
+} tBTA_DM_API_LINK_POLICY;
+
+/* data type for BTA_DM_API_AUTH_REPLY_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_SERVICE_ID service;
+ tBTA_AUTH_RESP response;
+} tBTA_DM_API_AUTH_REPLY;
+
+/* data type for BTA_DM_API_LOC_OOB_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+} tBTA_DM_API_LOC_OOB;
+
+/* data type for BTA_DM_API_CONFIRM_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ BOOLEAN accept;
+} tBTA_DM_API_CONFIRM;
+
+/* data type for BTA_DM_API_PASKY_CANCEL_EVT*/
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_DM_API_PASKY_CANCEL;
+
+/* data type for BTA_DM_CI_IO_REQ_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_IO_CAP io_cap;
+ tBTA_OOB_DATA oob_data;
+ tBTA_AUTH_REQ auth_req;
+} tBTA_DM_CI_IO_REQ;
+
+/* data type for BTA_DM_CI_RMT_OOB_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ BT_OCTET16 c;
+ BT_OCTET16 r;
+ BOOLEAN accept;
+} tBTA_DM_CI_RMT_OOB;
+
+/* data type for BTA_DM_REMT_NAME_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_SEARCH result;
+} tBTA_DM_REM_NAME;
+
+/* data type for tBTA_DM_DISC_RESULT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_SEARCH result;
+} tBTA_DM_DISC_RESULT;
+
+
+/* data type for BTA_DM_INQUIRY_CMPL_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 num;
+} tBTA_DM_INQUIRY_CMPL;
+
+/* data type for BTA_DM_SDP_RESULT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 sdp_result;
+} tBTA_DM_SDP_RESULT;
+
+/* data type for BTA_API_DM_SIG_STRENGTH_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_SIG_STRENGTH_MASK mask;
+ UINT16 period;
+ BOOLEAN start;
+} tBTA_API_DM_SIG_STRENGTH;
+
+/* data type for tBTA_API_DM_TX_INQPWR */
+typedef struct
+{
+ BT_HDR hdr;
+ INT8 tx_power;
+}tBTA_API_DM_TX_INQPWR;
+
+/* data type for BTA_DM_ACL_CHANGE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTM_BL_EVENT event;
+ UINT8 busy_level;
+ BOOLEAN is_new;
+ UINT8 new_role;
+ BD_ADDR bd_addr;
+ UINT8 hci_status;
+} tBTA_DM_ACL_CHANGE;
+
+/* data type for BTA_DM_PM_BTM_STATUS_EVT */
+typedef struct
+{
+
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTM_PM_STATUS status;
+ UINT16 value;
+ UINT8 hci_status;
+
+} tBTA_DM_PM_BTM_STATUS;
+
+/* data type for BTA_DM_PM_TIMER_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+
+} tBTA_DM_PM_TIMER;
+
+
+/* data type for BTA_DM_API_ADD_DEVICE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ DEV_CLASS dc;
+ LINK_KEY link_key;
+ tBTA_SERVICE_MASK tm;
+ BOOLEAN is_trusted;
+ UINT8 key_type;
+ tBTA_IO_CAP io_cap;
+ BOOLEAN link_key_known;
+ BOOLEAN dc_known;
+ BD_NAME bd_name;
+ BD_FEATURES features;
+} tBTA_DM_API_ADD_DEVICE;
+
+/* data type for BTA_DM_API_REMOVE_ACL_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_DM_API_REMOVE_DEVICE;
+
+/* data type for BTA_DM_API_EXECUTE_CBACK_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ void * p_param;
+ tBTA_DM_EXEC_CBACK *p_exec_cback;
+} tBTA_DM_API_EXECUTE_CBACK;
+
+/* data type for tBTA_DM_API_SET_ENCRYPTION */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_ENCRYPT_CBACK *p_callback;
+ tBTA_DM_BLE_SEC_ACT sec_act;
+ BD_ADDR bd_addr;
+} tBTA_DM_API_SET_ENCRYPTION;
+
+#if BLE_INCLUDED == TRUE
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_LE_KEY_VALUE blekey;
+ tBTA_LE_KEY_TYPE key_type;
+
+}tBTA_DM_API_ADD_BLEKEY;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBT_DEVICE_TYPE dev_type ;
+ tBLE_ADDR_TYPE addr_type;
+
+}tBTA_DM_API_ADD_BLE_DEVICE;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ BOOLEAN accept;
+ UINT32 passkey;
+}tBTA_DM_API_PASSKEY_REPLY;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_DM_BLE_SEC_GRANT res;
+}tBTA_DM_API_BLE_SEC_GRANT;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_BLE_CONN_TYPE bg_conn_type;
+ tBTA_DM_BLE_SEL_CBACK *p_select_cback;
+}tBTA_DM_API_BLE_SET_BG_CONN_TYPE;
+
+/* set prefered BLE connection parameters for a device */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR peer_bda;
+ UINT16 conn_int_min;
+ UINT16 conn_int_max;
+ UINT16 supervision_tout;
+ UINT16 slave_latency;
+
+}tBTA_DM_API_BLE_CONN_PARAMS;
+
+/* set scan parameter for BLE connections */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 scan_int;
+ UINT16 scan_window;
+}tBTA_DM_API_BLE_SCAN_PARAMS;
+
+#endif
+
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN enable_or_disable;
+}tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT;
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+/* data type for BTA_DM_API_UPDATE_EIR_UUID_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN is_add;
+ tBT_UUID uuid;
+}tBTA_DM_API_UPDATE_EIR_UUID;
+#endif
+
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+/* data type for BTA_DM_API_SET_EIR_CONFIG_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_DM_EIR_CONF *p_eir_cfg;
+}tBTA_DM_API_SET_EIR_CONFIG;
+#endif
+
+/* union of all data types */
+typedef union
+{
+ /* GKI event buffer header */
+ BT_HDR hdr;
+ tBTA_DM_API_ENABLE enable;
+
+ tBTA_DM_API_SET_NAME set_name;
+
+ tBTA_DM_API_SET_VISIBILITY set_visibility;
+
+ tBTA_DM_API_SET_AFH_CHANNELS_EVT set_afhchannels;
+
+ tBTA_DM_API_VENDOR_SPECIFIC_COMMAND vendor_command;
+
+ tBTA_DM_API_ADD_DEVICE add_dev;
+
+ tBTA_DM_API_REMOVE_DEVICE remove_dev;
+
+ tBTA_DM_API_SEARCH search;
+
+ tBTA_DM_API_DISCOVER discover;
+
+ tBTA_DM_API_BOND bond;
+
+ tBTA_DM_API_BOND_CANCEL bond_cancel;
+
+ tBTA_DM_API_PIN_REPLY pin_reply;
+ tBTA_DM_API_LINK_POLICY link_policy;
+
+ tBTA_DM_API_LOC_OOB loc_oob;
+ tBTA_DM_API_CONFIRM confirm;
+ tBTA_DM_API_PASKY_CANCEL passkey_cancel;
+ tBTA_DM_CI_IO_REQ ci_io_req;
+ tBTA_DM_CI_RMT_OOB ci_rmt_oob;
+
+ tBTA_DM_API_AUTH_REPLY auth_reply;
+
+ tBTA_DM_REM_NAME rem_name;
+
+ tBTA_DM_DISC_RESULT disc_result;
+
+ tBTA_DM_INQUIRY_CMPL inq_cmpl;
+
+ tBTA_DM_SDP_RESULT sdp_event;
+
+ tBTA_API_DM_SIG_STRENGTH sig_strength;
+
+ tBTA_API_DM_TX_INQPWR tx_inq_pwr;
+
+ tBTA_DM_ACL_CHANGE acl_change;
+
+ tBTA_DM_PM_BTM_STATUS pm_status;
+
+ tBTA_DM_PM_TIMER pm_timer;
+
+ tBTA_DM_API_DI_DISC di_disc;
+
+ tBTA_DM_API_EXECUTE_CBACK exec_cback;
+
+ tBTA_DM_API_SET_ENCRYPTION set_encryption;
+
+#if BLE_INCLUDED == TRUE
+ tBTA_DM_API_ADD_BLEKEY add_ble_key;
+ tBTA_DM_API_ADD_BLE_DEVICE add_ble_device;
+ tBTA_DM_API_PASSKEY_REPLY ble_passkey_reply;
+ tBTA_DM_API_BLE_SEC_GRANT ble_sec_grant;
+ tBTA_DM_API_BLE_SET_BG_CONN_TYPE ble_set_bd_conn_type;
+ tBTA_DM_API_BLE_CONN_PARAMS ble_set_conn_params;
+ tBTA_DM_API_BLE_SCAN_PARAMS ble_set_scan_params;
+#endif
+
+ tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT set_afh_channel_assessment;
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ tBTA_DM_API_UPDATE_EIR_UUID update_eir_uuid;
+#endif
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+ tBTA_DM_API_SET_EIR_CONFIG set_eir_cfg;
+#endif
+
+} tBTA_DM_MSG;
+
+
+#define BTA_DM_NUM_PEER_DEVICE 7
+
+#define BTA_DM_NOT_CONNECTED 0
+#define BTA_DM_CONNECTED 1
+#define BTA_DM_UNPAIRING 2
+typedef UINT8 tBTA_DM_CONN_STATE;
+
+
+#define BTA_DM_DI_NONE 0x00 /* nothing special */
+#define BTA_DM_DI_USE_SSR 0x10 /* set this bit if ssr is supported for this link */
+#define BTA_DM_DI_AV_ACTIVE 0x20 /* set this bit if AV is active for this link */
+#define BTA_DM_DI_SET_SNIFF 0x01 /* set this bit if call BTM_SetPowerMode(sniff) */
+#define BTA_DM_DI_INT_SNIFF 0x02 /* set this bit if call BTM_SetPowerMode(sniff) & enter sniff mode */
+#define BTA_DM_DI_ACP_SNIFF 0x04 /* set this bit if peer init sniff */
+typedef UINT8 tBTA_DM_DEV_INFO;
+
+typedef struct
+{
+ BD_ADDR peer_bdaddr;
+ UINT16 link_policy;
+ tBTA_DM_CONN_STATE conn_state;
+ tBTA_PREF_ROLES pref_role;
+ BOOLEAN in_use;
+ tBTA_DM_DEV_INFO info;
+#if (BTM_SSR_INCLUDED == TRUE)
+ tBTM_PM_STATUS prev_low; /* previous low power mode used */
+#endif
+ tBTA_DM_PM_ACTTION pm_mode_attempted;
+ tBTA_DM_PM_ACTTION pm_mode_failed;
+
+} tBTA_DM_PEER_DEVICE;
+
+
+
+/* structure to store list of
+ active connections */
+typedef struct
+{
+ tBTA_DM_PEER_DEVICE peer_device[BTA_DM_NUM_PEER_DEVICE];
+ UINT8 count;
+
+} tBTA_DM_ACTIVE_LINK;
+
+
+typedef struct
+{
+ BD_ADDR peer_bdaddr;
+ tBTA_SYS_ID id;
+ UINT8 app_id;
+ tBTA_SYS_CONN_STATUS state;
+
+
+} tBTA_DM_SRVCS;
+
+#define BTA_DM_NUM_CONN_SRVS 5
+
+typedef struct
+{
+
+ UINT8 count;
+ tBTA_DM_SRVCS conn_srvc[BTA_DM_NUM_CONN_SRVS];
+
+} tBTA_DM_CONNECTED_SRVCS;
+
+typedef struct
+{
+ TIMER_LIST_ENT timer;
+ BD_ADDR peer_bdaddr;
+ BOOLEAN in_use;
+
+} tBTA_PM_TIMER;
+
+extern tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
+
+#define BTA_DM_NUM_PM_TIMER 3
+
+/* DM control block */
+typedef struct
+{
+ BOOLEAN is_bta_dm_active;
+ tBTA_DM_ACTIVE_LINK device_list;
+ tBTA_DM_SEC_CBACK *p_sec_cback;
+ TIMER_LIST_ENT signal_strength_timer;
+ tBTA_SIG_STRENGTH_MASK signal_strength_mask;
+ UINT16 state;
+ UINT16 signal_strength_period;
+ BOOLEAN disabling;
+ TIMER_LIST_ENT disable_timer;
+ UINT32 wbt_sdp_handle; /* WIDCOMM Extensions SDP record handle */
+ UINT8 wbt_scn; /* WIDCOMM Extensions SCN */
+ UINT8 num_master_only;
+ UINT8 pm_id;
+ tBTA_PM_TIMER pm_timer[BTA_DM_NUM_PM_TIMER];
+ UINT32 role_policy_mask; /* the bits set indicates the modules that wants to remove role switch from the default link policy */
+ UINT16 cur_policy; /* current default link policy */
+ UINT16 rs_event; /* the event waiting for role switch */
+ UINT8 cur_av_count; /* current AV connecions */
+ BOOLEAN disable_pair_mode; /* disable pair mode or not */
+ BOOLEAN conn_paired_only; /* allow connectable to paired device only or not */
+ tBTA_DM_API_SEARCH search_msg;
+ UINT16 page_scan_interval;
+ UINT16 page_scan_window;
+ UINT16 inquiry_scan_interval;
+ UINT16 inquiry_scan_window;
+
+ /* Storage for pin code request parameters */
+ BD_ADDR pin_bd_addr;
+ DEV_CLASS pin_dev_class;
+ tBTA_DM_SEC_EVT pin_evt;
+ UINT32 num_val; /* the numeric value for comparison. If just_works, do not show this number to UI */
+ BOOLEAN just_works; /* TRUE, if "Just Works" association model */
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )
+ /* store UUID list for EIR */
+ TIMER_LIST_ENT app_ready_timer;
+ UINT32 eir_uuid[BTM_EIR_SERVICE_ARRAY_SIZE];
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ tBT_UUID custom_uuid[BTA_EIR_SERVER_NUM_CUSTOM_UUID];
+#endif
+
+#endif
+
+ tBTA_DM_ENCRYPT_CBACK *p_encrypt_cback;
+ tBTA_DM_BLE_SEC_ACT sec_act;
+ TIMER_LIST_ENT switch_delay_timer;
+
+} tBTA_DM_CB;
+
+#ifndef BTA_DM_SDP_DB_SIZE
+#define BTA_DM_SDP_DB_SIZE 250
+#endif
+
+/* DM search control block */
+typedef struct
+{
+
+ tBTA_DM_SEARCH_CBACK * p_search_cback;
+ tBTM_INQ_INFO * p_btm_inq_info;
+ tBTA_SERVICE_MASK services;
+ tBTA_SERVICE_MASK services_to_search;
+ tBTA_SERVICE_MASK services_found;
+ tSDP_DISCOVERY_DB * p_sdp_db;
+ UINT16 state;
+ BD_ADDR peer_bdaddr;
+ BOOLEAN name_discover_done;
+ char peer_name[BD_NAME_LEN];
+ TIMER_LIST_ENT search_timer;
+ UINT8 service_index;
+ tBTA_DM_MSG * p_search_queue; /* search or discover commands during search cancel stored here */
+ BOOLEAN wait_disc;
+ BOOLEAN sdp_results;
+ tSDP_UUID uuid;
+ UINT8 peer_scn;
+ BOOLEAN sdp_search;
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+ tBTA_GATTC_IF client_if;
+ UINT8 num_uuid;
+ tBT_UUID *p_srvc_uuid;
+ UINT8 uuid_to_search;
+ BOOLEAN gatt_disc_active;
+ UINT16 conn_id;
+ UINT8 * p_ble_rawdata;
+ UINT32 ble_raw_size;
+ UINT32 ble_raw_used;
+#endif
+#endif
+
+
+} tBTA_DM_SEARCH_CB;
+
+/* DI control block */
+typedef struct
+{
+ tSDP_DISCOVERY_DB * p_di_db; /* pointer to the DI discovery database */
+ UINT8 di_num; /* total local DI record number */
+ UINT32 di_handle[BTA_DI_NUM_MAX]; /* local DI record handle, the first one is primary record */
+}tBTA_DM_DI_CB;
+
+/* DM search state */
+enum
+{
+
+ BTA_DM_SEARCH_IDLE,
+ BTA_DM_SEARCH_ACTIVE,
+ BTA_DM_SEARCH_CANCELLING,
+ BTA_DM_DISCOVER_ACTIVE
+
+};
+
+
+
+typedef struct
+{
+ DEV_CLASS dev_class; /* local device class */
+ UINT16 policy_settings; /* link policy setting hold, sniff, park, MS switch */
+ UINT16 page_timeout; /* timeout for page in slots */
+ UINT16 link_timeout; /* link supervision timeout in slots */
+ BOOLEAN avoid_scatter; /* TRUE to avoid scatternet when av is streaming (be the master) */
+
+} tBTA_DM_CFG;
+
+extern const UINT32 bta_service_id_to_btm_srv_id_lkup_tbl[];
+
+extern const tBTA_DM_CFG bta_dm_cfg;
+
+
+
+#define BTA_ALL_APP_ID 0xff
+
+typedef struct
+{
+ UINT8 id;
+ UINT8 app_id;
+ UINT8 cfg;
+
+} tBTA_DM_RM ;
+
+extern tBTA_DM_CFG *p_bta_dm_cfg;
+extern tBTA_DM_RM *p_bta_dm_rm_cfg;
+
+typedef struct
+{
+
+ UINT8 id;
+ UINT8 app_id;
+ UINT8 spec_idx; /* index of spec table to use */
+
+} tBTA_DM_PM_CFG;
+
+
+typedef struct
+{
+
+ tBTA_DM_PM_ACTTION power_mode;
+ UINT16 timeout;
+
+} tBTA_DM_PM_ACTN;
+
+typedef struct
+{
+
+ UINT8 allow_mask; /* mask of sniff/hold/park modes to allow */
+#if (BTM_SSR_INCLUDED == TRUE)
+ UINT8 ssr; /* set SSR on conn open/unpark */
+#endif
+ tBTA_DM_PM_ACTN actn_tbl [BTA_DM_PM_NUM_EVTS][2];
+
+} tBTA_DM_PM_SPEC;
+
+typedef struct
+{
+ UINT16 max_lat;
+ UINT16 min_rmt_to;
+ UINT16 min_loc_to;
+} tBTA_DM_SSR_SPEC;
+
+typedef struct
+{
+ UINT16 manufacturer;
+ UINT16 lmp_sub_version;
+ UINT8 lmp_version;
+}tBTA_DM_LMP_VER_INFO;
+
+extern tBTA_DM_PM_CFG *p_bta_dm_pm_cfg;
+extern tBTA_DM_PM_SPEC *p_bta_dm_pm_spec;
+extern tBTM_PM_PWR_MD *p_bta_dm_pm_md;
+#if (BTM_SSR_INCLUDED == TRUE)
+extern tBTA_DM_SSR_SPEC *p_bta_dm_ssr_spec;
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
+/* update dynamic BRCM Aware EIR data */
+extern const tBTA_DM_EIR_CONF bta_dm_eir_cfg;
+extern tBTA_DM_EIR_CONF *p_bta_dm_eir_cfg;
+#endif
+
+/* DM control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_CB bta_dm_cb;
+#else
+extern tBTA_DM_CB *bta_dm_cb_ptr;
+#define bta_dm_cb (*bta_dm_cb_ptr)
+#endif
+
+/* DM search control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_SEARCH_CB bta_dm_search_cb;
+#else
+extern tBTA_DM_SEARCH_CB *bta_dm_search_cb_ptr;
+#define bta_dm_search_cb (*bta_dm_search_cb_ptr)
+#endif
+
+/* DI control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_DI_CB bta_dm_di_cb;
+#else
+extern tBTA_DM_DI_CB *bta_dm_di_cb_ptr;
+#define bta_dm_di_cb (*bta_dm_di_cb_ptr)
+#endif
+
+extern BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg);
+extern void bta_dm_sm_disable( void );
+extern BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg);
+extern void bta_dm_search_sm_disable( void );
+
+
+extern void bta_dm_enable (tBTA_DM_MSG *p_data);
+extern void bta_dm_disable (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_dev_name (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_visibility (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_afhchannels (tBTA_DM_MSG *p_data);
+extern void bta_dm_vendor_spec_command(tBTA_DM_MSG *p_data);
+extern void bta_dm_bond (tBTA_DM_MSG *p_data);
+extern void bta_dm_bond_cancel (tBTA_DM_MSG *p_data);
+extern void bta_dm_pin_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_link_policy (tBTA_DM_MSG *p_data);
+extern void bta_dm_auth_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_signal_strength(tBTA_DM_MSG *p_data);
+extern void bta_dm_tx_inqpower(tBTA_DM_MSG *p_data);
+extern void bta_dm_acl_change(tBTA_DM_MSG *p_data);
+extern void bta_dm_add_device (tBTA_DM_MSG *p_data);
+extern void bta_dm_remove_device (tBTA_DM_MSG *p_data);
+
+
+extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data);
+extern void bta_dm_pm_timer(tBTA_DM_MSG *p_data);
+extern void bta_dm_add_ampkey (tBTA_DM_MSG *p_data);
+
+#if BLE_INCLUDED == TRUE
+extern void bta_dm_add_blekey (tBTA_DM_MSG *p_data);
+extern void bta_dm_add_ble_device (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_security_grant (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_scan_params (tBTA_DM_MSG *p_data);
+#endif
+extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
+extern void bta_dm_confirm(tBTA_DM_MSG *p_data);
+extern void bta_dm_passkey_cancel(tBTA_DM_MSG *p_data);
+#if (BTM_OOB_INCLUDED == TRUE)
+extern void bta_dm_loc_oob(tBTA_DM_MSG *p_data);
+extern void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data);
+extern void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data);
+#endif /* BTM_OOB_INCLUDED */
+
+extern void bta_dm_init_pm(void);
+extern void bta_dm_disable_pm(void);
+
+extern void bta_dm_search_start (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel (tBTA_DM_MSG *p_data);
+extern void bta_dm_discover (tBTA_DM_MSG *p_data);
+extern void bta_dm_di_disc (tBTA_DM_MSG *p_data);
+extern void bta_dm_inq_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_rmt_name (tBTA_DM_MSG *p_data);
+extern void bta_dm_sdp_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_free_sdp_db (tBTA_DM_MSG *p_data);
+extern void bta_dm_disc_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_discovery_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_queue_search (tBTA_DM_MSG *p_data);
+extern void bta_dm_queue_disc (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_clear_queue (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data);
+extern void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data);
+extern tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr);
+
+extern void bta_dm_pm_active(BD_ADDR peer_addr);
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
+void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding);
+#else
+#define bta_dm_eir_update_uuid(x, y)
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+extern void bta_dm_update_eir_uuid (tBTA_DM_MSG *p_data);
+#endif
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+extern void bta_dm_set_eir_config (tBTA_DM_MSG *p_data);
+#endif
+extern void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data);
+extern void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data);
+extern void bta_dm_execute_callback(tBTA_DM_MSG *p_data);
+
+extern void bta_dm_set_afh_channel_assesment(tBTA_DM_MSG *p_data);
+
+#endif /* BTA_DM_INT_H */
+
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
new file mode 100644
index 0000000..a2fec04
--- /dev/null
+++ b/bta/dm/bta_dm_main.c
@@ -0,0 +1,345 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the main implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_dm_int.h"
+
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_DM_CB bta_dm_cb;
+tBTA_DM_SEARCH_CB bta_dm_search_cb;
+tBTA_DM_DI_CB bta_dm_di_cb;
+#endif
+
+
+#define BTA_DM_NUM_ACTIONS (BTA_DM_MAX_EVT & 0x00ff)
+
+/* type for action functions */
+typedef void (*tBTA_DM_ACTION)(tBTA_DM_MSG *p_data);
+
+/* action function list */
+const tBTA_DM_ACTION bta_dm_action[] =
+{
+
+ /* device manager local device API events */
+ bta_dm_enable, /* 0 BTA_DM_API_ENABLE_EVT */
+ bta_dm_disable, /* 1 BTA_DM_API_DISABLE_EVT */
+ bta_dm_set_dev_name, /* 2 BTA_DM_API_SET_NAME_EVT */
+ bta_dm_set_visibility, /* 3 BTA_DM_API_SET_VISIBILITY_EVT */
+ bta_dm_set_afhchannels, /* 4 BTA_DM_API_SET_AFH_CHANNELS_EVT */
+ bta_dm_signal_strength, /* 5 BTA_API_DM_SIG_STRENGTH_EVT */
+ bta_dm_vendor_spec_command,/* 6 BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT */
+ bta_dm_tx_inqpower, /* 7 BTA_DM_API_SIG_STRENGTH_EVT */
+ bta_dm_acl_change, /* 8 BTA_DM_ACL_CHANGE_EVT */
+ bta_dm_add_device, /* 9 BTA_DM_API_ADD_DEVICE_EVT */
+
+ /* security API events */
+ bta_dm_bond, /* 10 BTA_DM_API_BOND_EVT */
+ bta_dm_bond_cancel, /* 11 BTA_DM_API_BOND_CANCEL_EVT */
+ bta_dm_pin_reply, /* 12 BTA_DM_API_PIN_REPLY_EVT */
+ bta_dm_link_policy, /* 13 BTA_DM_API_LINK_POLICY_EVT */
+ bta_dm_auth_reply, /* 14 BTA_DM_API_AUTH_REPLY_EVT */
+
+ /* power manger events */
+ bta_dm_pm_btm_status, /* 15 BTA_DM_PM_BTM_STATUS_EVT */
+ bta_dm_pm_timer, /* 16 BTA_DM_PM_TIMER_EVT*/
+
+ /* simple pairing events */
+ bta_dm_confirm, /* 17 BTA_DM_API_CONFIRM_EVT */
+
+ bta_dm_set_encryption, /* BTA_DM_API_SET_ENCRYPTION_EVT */
+
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+ bta_dm_passkey_cancel, /* 19 BTA_DM_API_PASKY_CANCEL_EVT */
+#endif
+#if (BTM_OOB_INCLUDED == TRUE)
+ bta_dm_loc_oob, /* 20 BTA_DM_API_LOC_OOB_EVT */
+ bta_dm_ci_io_req_act, /* 21 BTA_DM_CI_IO_REQ_EVT */
+ bta_dm_ci_rmt_oob_act, /* 22 BTA_DM_CI_RMT_OOB_EVT */
+#endif /* BTM_OOB_INCLUDED */
+
+ bta_dm_remove_device, /* BTA_DM_API_REMOVE_DEVICE_EVT */
+
+#if BLE_INCLUDED == TRUE
+ bta_dm_add_blekey, /* BTA_DM_API_ADD_BLEKEY_EVT */
+ bta_dm_add_ble_device, /* BTA_DM_API_ADD_BLEDEVICE_EVT */
+ bta_dm_ble_passkey_reply, /* BTA_DM_API_BLE_PASSKEY_REPLY_EVT */
+ bta_dm_security_grant,
+ bta_dm_ble_set_bg_conn_type,
+ bta_dm_ble_set_conn_params, /* BTA_DM_API_BLE_CONN_PARAM_EVT */
+ bta_dm_ble_set_scan_params, /* BTA_DM_API_BLE_SCAN_PARAM_EVT */
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+ bta_dm_update_eir_uuid, /* BTA_DM_API_UPDATE_EIR_UUID_EVT */
+#endif
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+ bta_dm_set_eir_config, /* BTA_DM_API_SET_EIR_CONFIG_EVT */
+#endif
+
+ bta_dm_enable_test_mode, /* BTA_DM_API_ENABLE_TEST_MODE_EVT */
+ bta_dm_disable_test_mode, /* BTA_DM_API_DISABLE_TEST_MODE_EVT */
+ bta_dm_execute_callback, /* BTA_DM_API_EXECUTE_CBACK_EVT */
+ bta_dm_set_afh_channel_assesment /* BTA_DM_API_SET_AFH_CHANNEL_ASSESMENT_EVT */
+};
+
+
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_DM_API_SEARCH, /* 0 bta_dm_search_start */
+ BTA_DM_API_SEARCH_CANCEL, /* 1 bta_dm_search_cancel */
+ BTA_DM_API_DISCOVER, /* 2 bta_dm_discover */
+ BTA_DM_INQUIRY_CMPL, /* 3 bta_dm_inq_cmpl */
+ BTA_DM_REMT_NAME, /* 4 bta_dm_rmt_name */
+ BTA_DM_SDP_RESULT, /* 5 bta_dm_sdp_result */
+ BTA_DM_SEARCH_CMPL, /* 6 bta_dm_search_cmpl*/
+ BTA_DM_FREE_SDP_DB, /* 7 bta_dm_free_sdp_db */
+ BTA_DM_DISC_RESULT, /* 8 bta_dm_disc_result */
+ BTA_DM_SEARCH_RESULT, /* 9 bta_dm_search_result */
+ BTA_DM_QUEUE_SEARCH, /* 10 bta_dm_queue_search */
+ BTA_DM_QUEUE_DISC, /* 11 bta_dm_queue_disc */
+ BTA_DM_SEARCH_CLEAR_QUEUE, /* 12 bta_dm_search_clear_queue */
+ BTA_DM_SEARCH_CANCEL_CMPL, /* 13 bta_dm_search_cancel_cmpl */
+ BTA_DM_SEARCH_CANCEL_NOTIFY, /* 14 bta_dm_search_cancel_notify */
+ BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, /* 15 bta_dm_search_cancel_transac_cmpl */
+ BTA_DM_DISC_RMT_NAME, /* 16 bta_dm_disc_rmt_name */
+ BTA_DM_API_DI_DISCOVER, /* 17 bta_dm_di_disc */
+ BTA_DM_SEARCH_NUM_ACTIONS /* 18 */
+};
+
+
+/* action function list */
+const tBTA_DM_ACTION bta_dm_search_action[] =
+{
+
+ bta_dm_search_start, /* 0 BTA_DM_API_SEARCH */
+ bta_dm_search_cancel, /* 1 BTA_DM_API_SEARCH_CANCEL */
+ bta_dm_discover, /* 2 BTA_DM_API_DISCOVER */
+ bta_dm_inq_cmpl, /* 3 BTA_DM_INQUIRY_CMPL */
+ bta_dm_rmt_name, /* 4 BTA_DM_REMT_NAME */
+ bta_dm_sdp_result, /* 5 BTA_DM_SDP_RESULT */
+ bta_dm_search_cmpl, /* 6 BTA_DM_SEARCH_CMPL */
+ bta_dm_free_sdp_db, /* 7 BTA_DM_FREE_SDP_DB */
+ bta_dm_disc_result, /* 8 BTA_DM_DISC_RESULT */
+ bta_dm_search_result, /* 9 BTA_DM_SEARCH_RESULT */
+ bta_dm_queue_search, /* 10 BTA_DM_QUEUE_SEARCH */
+ bta_dm_queue_disc, /* 11 BTA_DM_QUEUE_DISC */
+ bta_dm_search_clear_queue, /* 12 BTA_DM_SEARCH_CLEAR_QUEUE */
+ bta_dm_search_cancel_cmpl, /* 13 BTA_DM_SEARCH_CANCEL_CMPL */
+ bta_dm_search_cancel_notify, /* 14 BTA_DM_SEARCH_CANCEL_NOTIFY */
+ bta_dm_search_cancel_transac_cmpl, /* 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL */
+ bta_dm_disc_rmt_name, /* 16 BTA_DM_DISC_RMT_NAME */
+ bta_dm_di_disc /* 17 BTA_DM_API_DI_DISCOVER */
+};
+
+#define BTA_DM_SEARCH_IGNORE BTA_DM_SEARCH_NUM_ACTIONS
+/* state table information */
+#define BTA_DM_SEARCH_ACTIONS 2 /* number of actions */
+#define BTA_DM_SEARCH_NEXT_STATE 2 /* position of next state */
+#define BTA_DM_SEARCH_NUM_COLS 3 /* number of columns in state tables */
+
+
+
+/* state table for listen state */
+const UINT8 bta_dm_search_idle_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event Action 1 Action 2 Next State */
+/* API_SEARCH */ {BTA_DM_API_SEARCH, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE},
+/* API_SEARCH_CANCEL */ {BTA_DM_SEARCH_CANCEL_NOTIFY, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* API_SEARCH_DISC */ {BTA_DM_API_DISCOVER, BTA_DM_SEARCH_IGNORE, BTA_DM_DISCOVER_ACTIVE},
+/* INQUIRY_CMPL */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* REMT_NAME_EVT */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* SDP_RESULT_EVT */ {BTA_DM_FREE_SDP_DB, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* SEARCH_CMPL_EVT */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* API_DI_DISCOVER_EVT */ {BTA_DM_API_DI_DISCOVER, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE}
+
+};
+const UINT8 bta_dm_search_search_active_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event Action 1 Action 2 Next State */
+/* API_SEARCH */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE},
+/* API_SEARCH_CANCEL */ {BTA_DM_API_SEARCH_CANCEL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE},
+/* INQUIRY_CMPL */ {BTA_DM_INQUIRY_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE},
+/* REMT_NAME_EVT */ {BTA_DM_REMT_NAME, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE},
+/* SDP_RESULT_EVT */ {BTA_DM_SDP_RESULT, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE},
+/* SEARCH_CMPL_EVT */ {BTA_DM_SEARCH_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */ {BTA_DM_SEARCH_RESULT, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE},
+/* API_DI_DISCOVER_EVT */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_ACTIVE}
+
+
+};
+
+const UINT8 bta_dm_search_search_cancelling_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event Action 1 Action 2 Next State */
+/* API_SEARCH */ {BTA_DM_QUEUE_SEARCH, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_CANCEL */ {BTA_DM_SEARCH_CLEAR_QUEUE, BTA_DM_SEARCH_CANCEL_NOTIFY, BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */ {BTA_DM_QUEUE_DISC, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_CANCELLING},
+/* INQUIRY_CMPL */ {BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* REMT_NAME_EVT */ {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IDLE},
+/* SDP_RESULT_EVT */ {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IDLE},
+/* SEARCH_CMPL_EVT */ {BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */ {BTA_DM_SEARCH_CANCEL_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* API_DI_DISCOVER_EVT */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_CANCELLING}
+
+
+};
+
+const UINT8 bta_dm_search_disc_active_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event Action 1 Action 2 Next State */
+/* API_SEARCH */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_DISCOVER_ACTIVE},
+/* API_SEARCH_CANCEL */ {BTA_DM_SEARCH_CANCEL_NOTIFY, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_DISCOVER_ACTIVE},
+/* INQUIRY_CMPL */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_DISCOVER_ACTIVE},
+/* REMT_NAME_EVT */ {BTA_DM_DISC_RMT_NAME, BTA_DM_SEARCH_IGNORE, BTA_DM_DISCOVER_ACTIVE},
+/* SDP_RESULT_EVT */ {BTA_DM_SDP_RESULT, BTA_DM_SEARCH_IGNORE, BTA_DM_DISCOVER_ACTIVE},
+/* SEARCH_CMPL_EVT */ {BTA_DM_SEARCH_CMPL, BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */ {BTA_DM_DISC_RESULT, BTA_DM_SEARCH_IGNORE, BTA_DM_DISCOVER_ACTIVE},
+/* API_DI_DISCOVER_EVT */ {BTA_DM_SEARCH_IGNORE, BTA_DM_SEARCH_IGNORE, BTA_DM_DISCOVER_ACTIVE}
+
+};
+
+typedef const UINT8 (*tBTA_DM_ST_TBL)[BTA_DM_SEARCH_NUM_COLS];
+
+/* state table */
+const tBTA_DM_ST_TBL bta_dm_search_st_tbl[] = {
+ bta_dm_search_idle_st_table,
+ bta_dm_search_search_active_st_table,
+ bta_dm_search_search_cancelling_st_table,
+ bta_dm_search_disc_active_st_table
+};
+
+
+/*******************************************************************************
+**
+** Function bta_dm_sm_disable
+**
+** Description unregister BTA DM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_sm_disable( )
+{
+ bta_sys_deregister( BTA_ID_DM );
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_sm_execute
+**
+** Description State machine event handling function for DM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg)
+{
+ UINT16 event = p_msg->event & 0x00ff;
+
+ APPL_TRACE_EVENT1("bta_dm_sm_execute event:0x%x", event);
+
+ /* execute action functions */
+ if(event < BTA_DM_NUM_ACTIONS)
+ {
+ (*bta_dm_action[event])( (tBTA_DM_MSG*) p_msg);
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_sm_search_disable
+**
+** Description unregister BTA SEARCH DM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_search_sm_disable( )
+{
+ bta_sys_deregister( BTA_ID_DM_SEARCH );
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_search_sm_execute
+**
+** Description State machine event handling function for DM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg)
+{
+ tBTA_DM_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+ APPL_TRACE_EVENT2("bta_dm_search_sm_execute state:%d, event:0x%x",
+ bta_dm_search_cb.state, p_msg->event);
+
+ /* look up the state table for the current state */
+ state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state];
+
+ bta_dm_search_cb.state = state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE];
+
+
+ /* execute action functions */
+ for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++)
+ {
+ if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_DM_SEARCH_IGNORE)
+ {
+ (*bta_dm_search_action[action])( (tBTA_DM_MSG*) p_msg);
+ }
+ else
+ {
+ break;
+ }
+ }
+ return TRUE;
+}
+
diff --git a/bta/dm/bta_dm_pm.c b/bta/dm/bta_dm_pm.c
new file mode 100644
index 0000000..8a993de
--- /dev/null
+++ b/bta/dm/bta_dm_pm.c
@@ -0,0 +1,994 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the action functions for device manager state
+ * machine.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "btm_api.h"
+
+#include <string.h>
+
+
+static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+static void bta_dm_pm_set_mode(BD_ADDR peer_addr, BOOLEAN timed_out );
+static void bta_dm_pm_timer_cback(void *p_tle);
+static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status);
+static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr);
+static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index);
+static BOOLEAN bta_dm_pm_is_sco_active ();
+static void bta_dm_pm_hid_check(BOOLEAN bScoActive);
+static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable);
+#if (BTM_SSR_INCLUDED == TRUE)
+static void bta_dm_pm_ssr(BD_ADDR peer_addr);
+static void bta_dm_ssr_cfg_cback(UINT8 id, UINT8 app_id, UINT16 max_lat, UINT16 min_rmt_to);
+#endif
+
+tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
+
+
+/*******************************************************************************
+**
+** Function bta_dm_init_pm
+**
+** Description Initialises the BT low power manager
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_init_pm(void)
+{
+
+ memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
+
+ /* if there are no power manger entries, so not register */
+ if(p_bta_dm_pm_cfg[0].app_id != 0)
+ {
+ bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)bta_dm_pm_cback);
+
+#if (BTM_SSR_INCLUDED == TRUE)
+ bta_sys_ssr_cfg_register((tBTA_SYS_SSR_CFG_CBACK*)bta_dm_ssr_cfg_cback);
+#endif
+ BTM_PmRegister((BTM_PM_REG_SET | BTM_PM_REG_NOTIF), &bta_dm_cb.pm_id,
+ bta_dm_pm_btm_cback);
+ }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_disable_pm
+**
+** Description Disable PM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_disable_pm(void)
+{
+ UINT8 i;
+
+ bta_sys_pm_register(NULL);
+ BTM_PmRegister( BTM_PM_DEREG, &bta_dm_cb.pm_id, NULL);
+
+ /* Need to stop all active timers. */
+ for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+ {
+ if(bta_dm_cb.pm_timer[i].in_use)
+ {
+ APPL_TRACE_DEBUG1("stop dm_pm_timer:%d", i);
+ bta_sys_stop_timer(&bta_dm_cb.pm_timer[i].timer);
+ bta_dm_cb.pm_timer[i].in_use = FALSE;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_stop_timer
+**
+** Description stop a PM timer
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_pm_stop_timer(BD_ADDR peer_addr)
+{
+ UINT8 i;
+
+ for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+ {
+
+ if(bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr))
+ {
+ APPL_TRACE_DEBUG1("stop dm_pm_timer:%d", i);
+ bta_sys_stop_timer(&bta_dm_cb.pm_timer[i].timer);
+ bta_dm_cb.pm_timer[i].in_use = FALSE;
+ break;
+ }
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_cback
+**
+** Description Conn change callback from sys for low power management
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+
+ UINT8 i,j;
+ UINT16 policy_setting;
+ tBTM_STATUS btm_status;
+ tBTM_VERSION_INFO vers;
+#if (BTM_SSR_INCLUDED == TRUE)
+ int index = BTA_DM_PM_SSR0;
+#endif
+ tBTA_DM_PEER_DEVICE *p_dev;
+
+ APPL_TRACE_DEBUG3("bta_dm_pm_cback: st(%d), id(%d), app(%d)", status, id, app_id);
+
+ btm_status = BTM_ReadLocalVersion (&vers);
+ p_dev = bta_dm_find_peer_device(peer_addr);
+
+ /* Disable/Enable sniff policy on the SCO link if sco Up/Down. Will be removed in 2.2*/
+ if ((btm_status == BTM_SUCCESS) &&
+ (vers.manufacturer == LMP_COMPID_BROADCOM) &&
+ (vers.hci_version < HCI_PROTO_VERSION_2_0) &&
+ ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) )
+ {
+ bta_dm_pm_set_sniff_policy(p_dev, (status == BTA_SYS_SCO_OPEN));
+ }
+
+ /* find if there is an power mode entry for the service */
+ for(i=1; i<=p_bta_dm_pm_cfg[0].app_id; i++)
+ {
+
+ if((p_bta_dm_pm_cfg[i].id == id)
+ && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id )))
+ break;
+
+ }
+
+ /* if no entries are there for the app_id and subystem in p_bta_dm_pm_spec*/
+ if(i> p_bta_dm_pm_cfg[0].app_id)
+ return;
+
+ bta_dm_pm_stop_timer(peer_addr);
+ /*p_dev = bta_dm_find_peer_device(peer_addr);*/
+
+#if (BTM_SSR_INCLUDED == TRUE)
+ /* set SSR parameters on SYS CONN OPEN */
+ if((BTA_SYS_CONN_OPEN == status) && p_dev && (p_dev->info & BTA_DM_DI_USE_SSR))
+ {
+ index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
+ }
+#endif
+
+ /* if no action for the event */
+ if(p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_ACTION)
+ {
+#if (BTM_SSR_INCLUDED == TRUE)
+ if(BTA_DM_PM_SSR0 == index) /* and do not need to set SSR, return. */
+#endif
+ return;
+ }
+
+ for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+ {
+ /* check if an entry already present */
+ if((bta_dm_conn_srvcs.conn_srvc[j].id == id)
+ && (bta_dm_conn_srvcs.conn_srvc[j].app_id == app_id )
+ && !bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr))
+ break;
+
+ }
+
+ /* if subsystem has no more preference on the power mode remove
+ the cb */
+ if(p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_PREF)
+ {
+
+ if(j != bta_dm_conn_srvcs.count)
+ {
+ bta_dm_conn_srvcs.count--;
+
+ for(; j<bta_dm_conn_srvcs.count ; j++)
+ {
+
+ memcpy(&bta_dm_conn_srvcs.conn_srvc[j], &bta_dm_conn_srvcs.conn_srvc[j+1], sizeof(bta_dm_conn_srvcs.conn_srvc[j]));
+
+ }
+ }
+ else
+ {
+ APPL_TRACE_WARNING0("bta_dm_act no entry for connected service cbs");
+ return;
+ }
+ }
+ else if(j == bta_dm_conn_srvcs.count )
+ {
+ /* check if we have more connected service that cbs */
+ if(bta_dm_conn_srvcs.count == BTA_DM_NUM_CONN_SRVS)
+ {
+ APPL_TRACE_WARNING0("bta_dm_act no more connected service cbs");
+ return;
+ }
+
+ /* fill in a new cb */
+ bta_dm_conn_srvcs.conn_srvc[j].id = id;
+ bta_dm_conn_srvcs.conn_srvc[j].app_id = app_id;
+ bdcpy(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr);
+
+ APPL_TRACE_WARNING2("new conn_srvc id:%d, app_id:%d", id, app_id);
+
+ bta_dm_conn_srvcs.count++;
+ bta_dm_conn_srvcs.conn_srvc[j].state = status;
+ }
+ else
+ {
+ /* no service is added or removed. only updating status. */
+ bta_dm_conn_srvcs.conn_srvc[j].state = status;
+ }
+
+ if(p_dev)
+ {
+ p_dev->pm_mode_attempted = 0;
+ p_dev->pm_mode_failed = 0;
+ }
+
+#if (BTM_SSR_INCLUDED == TRUE)
+ if(p_bta_dm_ssr_spec[index].max_lat)
+ {
+ bta_dm_pm_ssr(peer_addr);
+ }
+#endif
+
+ bta_dm_pm_set_mode(peer_addr, FALSE);
+
+ /* perform the HID link workaround if needed
+ ** 1. If SCO up/down event is received OR
+ ** 2. If HID connection open is received and SCO is already active.
+ ** This will handle the case where HID connects when SCO already active
+ */
+ if ( (btm_status == BTM_SUCCESS) &&
+ ( ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) ||
+ ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active()) ) )
+ {
+ BOOLEAN bScoActive;
+ if (status == BTA_SYS_CONN_OPEN)
+ bScoActive = TRUE;
+ else
+ bScoActive = (status == BTA_SYS_SCO_OPEN);
+
+ bta_dm_pm_hid_check(bScoActive);
+ }
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_set_mode
+**
+** Description Set the power mode for the device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_pm_set_mode(BD_ADDR peer_addr, BOOLEAN timed_out )
+{
+
+ tBTA_DM_PM_ACTTION pm_action = BTA_DM_PM_NO_ACTION;
+ UINT16 timeout = 0;
+ UINT8 i,j;
+ tBTA_DM_PM_ACTTION failed_pm = 0;
+ tBTA_DM_PEER_DEVICE *p_peer_device = NULL;
+ tBTA_DM_PM_ACTTION allowed_modes = 0;
+ tBTA_DM_PM_ACTTION pref_modes = 0;
+ tBTA_DM_PM_CFG *p_pm_cfg;
+ tBTA_DM_PM_SPEC *p_pm_spec;
+ tBTA_DM_PM_ACTN *p_act0, *p_act1;
+ tBTA_DM_SRVCS *p_srvcs;
+
+
+ if(!bta_dm_cb.device_list.count)
+ return;
+
+ /* see if any attempt to put device in low power mode failed */
+ p_peer_device = bta_dm_find_peer_device(peer_addr);
+ /* if no peer device found return */
+ if (p_peer_device == NULL)
+ return;
+
+ failed_pm = p_peer_device->pm_mode_failed;
+
+ for(i=0; i<bta_dm_conn_srvcs.count ; i++)
+ {
+
+ p_srvcs = &bta_dm_conn_srvcs.conn_srvc[i];
+ if(!bdcmp(p_srvcs->peer_bdaddr, peer_addr))
+ {
+
+ /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
+ for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++)
+ {
+ if((p_bta_dm_pm_cfg[j].id == p_srvcs->id)
+ && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID ) ||
+ (p_bta_dm_pm_cfg[j].app_id == p_srvcs->app_id)))
+ break;
+ }
+
+ p_pm_cfg = &p_bta_dm_pm_cfg[j];
+ p_pm_spec = &p_bta_dm_pm_spec[p_pm_cfg->spec_idx];
+ p_act0 = &p_pm_spec->actn_tbl[p_srvcs->state][0];
+ p_act1 = &p_pm_spec->actn_tbl[p_srvcs->state][1];
+
+ APPL_TRACE_DEBUG3("bta_dm_pm_set_mode: srvcsid: %d, state: %d, j: %d", p_srvcs->id, p_srvcs->state, j);
+ allowed_modes |= p_pm_spec->allow_mask;
+
+ /* PM actions are in the order of strictness */
+
+ /* first check if the first preference is ok */
+ if(!(failed_pm & p_act0->power_mode))
+ {
+ pref_modes |= p_act0->power_mode;
+
+ if(p_act0->power_mode > pm_action)
+ {
+ pm_action = p_act0->power_mode;
+ timeout = p_act0->timeout;
+
+ }
+ }
+ /* if first preference has already failed, try second preference */
+ else if(!(failed_pm & p_act1->power_mode))
+ {
+ pref_modes |= p_act1->power_mode;
+
+ if(p_act1->power_mode > pm_action)
+ {
+ pm_action = p_act1->power_mode;
+ timeout = p_act1->timeout;
+
+ }
+ }
+ }
+ }
+
+ if(pm_action & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF))
+ {
+
+ /* some service don't like the mode */
+ if(!(allowed_modes & pm_action))
+ {
+
+ /* select the other mode if its allowed and preferred, otherwise 0 which is BTA_DM_PM_NO_ACTION */
+ pm_action = (allowed_modes & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & pref_modes);
+
+ /* no timeout needed if no action is required */
+ if(pm_action == BTA_DM_PM_NO_ACTION)
+ {
+ timeout = 0;
+ }
+
+ }
+
+
+ }
+
+ if(!timed_out && timeout)
+ {
+
+ for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+ {
+
+ if(!bta_dm_cb.pm_timer[i].in_use)
+ {
+ bta_dm_cb.pm_timer[i].in_use = TRUE;
+ bdcpy(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr);
+ bta_dm_cb.pm_timer[i].timer.p_cback = bta_dm_pm_timer_cback;
+ bta_sys_start_timer(&bta_dm_cb.pm_timer[i].timer, 0, timeout);
+ APPL_TRACE_DEBUG2("start dm_pm_timer:%d, %d", i, timeout);
+ return;
+
+ }
+
+ }
+
+ /* no more timers */
+ if(i==BTA_DM_NUM_PM_TIMER)
+ {
+ APPL_TRACE_WARNING0("bta_dm_act dm_pm_timer no more");
+ return;
+ }
+ }
+
+ if(pm_action == BTA_DM_PM_NO_ACTION)
+ {
+
+
+ }
+ else if(pm_action == BTA_DM_PM_PARK)
+ {
+ p_peer_device->pm_mode_attempted = BTA_DM_PM_PARK;
+ bta_dm_pm_park(peer_addr);
+
+ }
+ else if(pm_action & BTA_DM_PM_SNIFF)
+ {
+ /* dont initiate SNIFF, if link_policy has it disabled */
+ if (p_peer_device->link_policy & HCI_ENABLE_SNIFF_MODE)
+ {
+ p_peer_device->pm_mode_attempted = BTA_DM_PM_SNIFF;
+ bta_dm_pm_sniff(p_peer_device, (UINT8)(pm_action & 0x0F) );
+ }
+ else
+ {
+ APPL_TRACE_DEBUG0("bta_dm_pm_set_mode: Link policy disallows SNIFF, ignore request");
+ }
+ }
+ else if(pm_action == BTA_DM_PM_ACTIVE)
+ {
+
+ bta_dm_pm_active(peer_addr);
+
+ }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ag_pm_park
+**
+** Description Switch to park mode.
+**
+**
+** Returns TRUE if park attempted, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr)
+{
+
+ tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE;
+
+ /* if not in park mode, switch to park */
+ BTM_ReadPowerMode(peer_addr, &mode);
+
+ if(mode != BTM_PM_MD_PARK)
+ {
+ BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &p_bta_dm_pm_md[BTA_DM_PM_PARK_IDX]);
+ }
+ return TRUE;
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ag_pm_sniff
+**
+** Description Switch to sniff mode.
+**
+**
+** Returns TRUE if sniff attempted, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index)
+{
+ tBTM_PM_MODE mode = BTM_PM_STS_ACTIVE;
+ tBTM_PM_PWR_MD pwr_md;
+ tBTM_STATUS status;
+
+ BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode);
+
+#if (BTM_SSR_INCLUDED == TRUE)
+ APPL_TRACE_DEBUG3("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index, p_peer_dev->info);
+ if (mode != BTM_PM_MD_SNIFF ||
+ (HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures ()) &&
+ HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadRemoteFeatures (p_peer_dev->peer_bdaddr)) &&
+ !(p_peer_dev->info & BTA_DM_DI_USE_SSR)))
+#else
+ APPL_TRACE_DEBUG2("bta_dm_pm_sniff cur:%d, idx:%d", mode, index);
+ if(mode != BTM_PM_MD_SNIFF)
+#endif
+ {
+ /* if the current mode is not sniff, issue the sniff command.
+ * If sniff, but SSR is not used in this link, still issue the command */
+ memcpy(&pwr_md, &p_bta_dm_pm_md[index], sizeof (tBTM_PM_PWR_MD));
+ if (p_peer_dev->info & BTA_DM_DI_INT_SNIFF)
+ {
+ pwr_md.mode |= BTM_PM_MD_FORCE;
+ }
+ status = BTM_SetPowerMode (bta_dm_cb.pm_id, p_peer_dev->peer_bdaddr, &pwr_md);
+ if (status == BTM_CMD_STORED|| status == BTM_CMD_STARTED)
+ {
+ p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF);
+ p_peer_dev->info |= BTA_DM_DI_SET_SNIFF;
+ }
+ else if (status == BTM_SUCCESS)
+ {
+ APPL_TRACE_DEBUG0("bta_dm_pm_sniff BTM_SetPowerMode() returns BTM_SUCCESS");
+ p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+ }
+ else /* error */
+ {
+ APPL_TRACE_ERROR1("bta_dm_pm_sniff BTM_SetPowerMode() returns ERROR status=%d", status);
+ p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+ }
+ }
+ /* else already in sniff and is using SSR, do nothing */
+
+ return TRUE;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_ssr
+**
+** Description checks and sends SSR parameters
+**
+** Returns void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+static void bta_dm_pm_ssr(BD_ADDR peer_addr)
+{
+ tBTA_DM_SSR_SPEC *p_spec, *p_spec_cur;
+ UINT8 i,j;
+ int ssr = BTA_DM_PM_SSR0;
+
+ /* go through the connected services */
+ for(i=0; i<bta_dm_conn_srvcs.count ; i++)
+ {
+ if(!bdcmp(bta_dm_conn_srvcs.conn_srvc[i].peer_bdaddr, peer_addr))
+ {
+ /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
+ for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++)
+ {
+ /* find the associated p_bta_dm_pm_cfg */
+ if((p_bta_dm_pm_cfg[j].id == bta_dm_conn_srvcs.conn_srvc[i].id)
+ && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID )
+ || (p_bta_dm_pm_cfg[j].app_id == bta_dm_conn_srvcs.conn_srvc[i].app_id)))
+ {
+ APPL_TRACE_WARNING2("bta_dm_pm_ssr conn_srvc id:%d, app_id:%d",
+ bta_dm_conn_srvcs.conn_srvc[i].id, bta_dm_conn_srvcs.conn_srvc[i].app_id);
+ break;
+ }
+ }
+
+ /* find the ssr index with the smallest max latency. */
+ p_spec_cur = &p_bta_dm_ssr_spec[p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr];
+ p_spec = &p_bta_dm_ssr_spec[ssr];
+
+ if (p_spec_cur->max_lat < p_spec->max_lat ||
+ (ssr == BTA_DM_PM_SSR0 && p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr != BTA_DM_PM_SSR0))
+ {
+ ssr = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr;
+ }
+
+ }
+ }
+
+ p_spec = &p_bta_dm_ssr_spec[ssr];
+ APPL_TRACE_WARNING2("bta_dm_pm_ssr:%d, lat:%d", ssr, p_spec->max_lat);
+ if(p_spec->max_lat)
+ {
+ /* set the SSR parameters. */
+ BTM_SetSsrParams (peer_addr, p_spec->max_lat,
+ p_spec->min_rmt_to, p_spec->min_loc_to);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_dm_ssr_cfg_cback
+**
+** Description Conn change callback from sys for low power management
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_ssr_cfg_cback(UINT8 id, UINT8 app_id,
+ UINT16 max_lat, UINT16 min_rmt_to)
+{
+ tBTA_DM_SSR_SPEC *p_spec;
+ UINT8 i, index;
+ /* find if there is an power mode entry for the service */
+ for(i=1; i<=p_bta_dm_pm_cfg[0].app_id; i++)
+ {
+
+ if((p_bta_dm_pm_cfg[i].id == id)
+ && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id )))
+ break;
+
+ }
+ /* if no entries are there for the app_id and subystem in p_bta_dm_pm_spec*/
+ if(i> p_bta_dm_pm_cfg[0].app_id)
+ return;
+
+ index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
+
+ APPL_TRACE_DEBUG2("SSR parameter changed to: max_latency: %d min_tout: %d", max_lat, min_rmt_to);
+
+ p_spec = &p_bta_dm_ssr_spec[index];
+ p_spec->max_lat = max_lat;
+ p_spec->min_rmt_to = min_rmt_to;
+}
+
+
+#endif
+/*******************************************************************************
+**
+** Function bta_dm_pm_active
+**
+** Description Brings connection to active mode
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_pm_active(BD_ADDR peer_addr)
+{
+ tBTM_PM_PWR_MD pm;
+
+ memset( (void*)&pm, 0, sizeof(pm));
+
+ /* switch to active mode */
+ pm.mode = BTM_PM_MD_ACTIVE;
+ BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &pm);
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_btm_cback
+**
+** Description BTM power manager callback.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status)
+{
+ tBTA_DM_PM_BTM_STATUS *p_buf;
+
+ if ((p_buf = (tBTA_DM_PM_BTM_STATUS *) GKI_getbuf(sizeof(tBTA_DM_PM_BTM_STATUS))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DM_PM_BTM_STATUS_EVT;
+ p_buf->status = status;
+ p_buf->value = value;
+ p_buf->hci_status = hci_status;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_timer_cback
+**
+** Description Power management timer callback.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_pm_timer_cback(void *p_tle)
+{
+ tBTA_DM_PM_TIMER *p_buf;
+ UINT8 i;
+
+ APPL_TRACE_WARNING0("dm_pm_timer expires");
+
+ for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+ {
+
+ if(bta_dm_cb.pm_timer[i].in_use)
+ {
+
+ if(&bta_dm_cb.pm_timer[i].timer == (TIMER_LIST_ENT*) p_tle)
+ {
+ APPL_TRACE_WARNING1("dm_pm_timer expires %d", i);
+ bta_dm_cb.pm_timer[i].in_use = FALSE;
+ break;
+ }
+
+ }
+
+ }
+
+
+ /* no more timers */
+ if(i==BTA_DM_NUM_PM_TIMER)
+ {
+ return;
+ }
+
+ if ((p_buf = (tBTA_DM_PM_TIMER *) GKI_getbuf(sizeof(tBTA_DM_PM_TIMER))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DM_PM_TIMER_EVT;
+ bdcpy(p_buf->bd_addr, bta_dm_cb.pm_timer[i].peer_bdaddr);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_btm_status
+**
+** Description Process pm status event from btm
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data)
+{
+
+ tBTA_DM_PEER_DEVICE *p_dev;
+ tBTA_DM_DEV_INFO info;
+
+ APPL_TRACE_DEBUG1("bta_dm_pm_btm_status:%d", p_data->pm_status.status);
+ p_dev = bta_dm_find_peer_device(p_data->pm_status.bd_addr);
+ if(NULL == p_dev)
+ return;
+
+ info = p_dev->info;
+ /* check new mode */
+ switch (p_data->pm_status.status)
+ {
+ case BTM_PM_STS_ACTIVE:
+ /* if our sniff or park attempt failed
+ we should not try it again*/
+ if (p_data->pm_status.hci_status != 0)
+ {
+ APPL_TRACE_ERROR1("bta_dm_pm_btm_status hci_status=%d", p_data->pm_status.hci_status);
+ p_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+
+ if(p_dev->pm_mode_attempted &(BTA_DM_PM_PARK | BTA_DM_PM_SNIFF))
+ {
+ p_dev->pm_mode_failed
+ |= ((BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & p_dev->pm_mode_attempted);
+ bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
+ bta_dm_pm_set_mode(p_data->pm_status.bd_addr, FALSE);
+ }
+ }
+ else
+ {
+#if (BTM_SSR_INCLUDED == TRUE)
+ if(p_dev->prev_low)
+ {
+ /* need to send the SSR paramaters to controller again */
+ bta_dm_pm_ssr(p_dev->peer_bdaddr);
+ }
+ p_dev->prev_low = BTM_PM_STS_ACTIVE;
+#endif
+ bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
+ bta_dm_pm_set_mode(p_data->pm_status.bd_addr, FALSE);
+ }
+ break;
+
+#if (BTM_SSR_INCLUDED == TRUE)
+ case BTM_PM_STS_PARK:
+ case BTM_PM_STS_HOLD:
+ /* save the previous low power mode - for SSR.
+ * SSR parameters are sent to controller on "conn open".
+ * the numbers stay good until park/hold/detach */
+ if(p_dev->info & BTA_DM_DI_USE_SSR)
+ p_dev->prev_low = p_data->pm_status.status;
+ break;
+
+ case BTM_PM_STS_SSR:
+ if(p_data->pm_status.value)
+ p_dev->info |= BTA_DM_DI_USE_SSR;
+ else
+ p_dev->info &= ~BTA_DM_DI_USE_SSR;
+ break;
+#endif
+ case BTM_PM_STS_SNIFF:
+ p_dev->info &= ~(BTA_DM_DI_SET_SNIFF|BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF);
+ if (info & BTA_DM_DI_SET_SNIFF)
+ p_dev->info |= BTA_DM_DI_INT_SNIFF;
+ else
+ p_dev->info |= BTA_DM_DI_ACP_SNIFF;
+ break;
+
+ case BTM_PM_STS_ERROR:
+ p_dev->info &= ~BTA_DM_DI_SET_SNIFF;
+ break;
+
+ default:
+ break;
+ }
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_timer
+**
+** Description Process pm timer event from btm
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_pm_timer(tBTA_DM_MSG *p_data)
+{
+
+ APPL_TRACE_WARNING0("proc dm_pm_timer expires");
+ bta_dm_pm_set_mode(p_data->pm_status.bd_addr, TRUE);
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_find_peer_device
+**
+** Description Given an address, find the associated control block.
+**
+** Returns tBTA_DM_PEER_DEVICE
+**
+*******************************************************************************/
+tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr)
+{
+ tBTA_DM_PEER_DEVICE *p_dev = NULL;
+ int i;
+
+ for(i=0; i<bta_dm_cb.device_list.count; i++)
+ {
+ if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr))
+ {
+ p_dev = &bta_dm_cb.device_list.peer_device[i];
+ break;
+ }
+
+ }
+ return p_dev;
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_is_sco_active
+**
+** Description Loop through connected services for HFP+State=SCO
+**
+** Returns BOOLEAN. TRUE if SCO active, else FALSE
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_is_sco_active ()
+{
+ int j;
+ BOOLEAN bScoActive = FALSE;
+
+ for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+ {
+ /* check if an entry already present */
+ if ( (bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_AG ) && (bta_dm_conn_srvcs.conn_srvc[j].state == BTA_SYS_SCO_OPEN) )
+ {
+ bScoActive = TRUE;
+ break;
+ }
+ }
+
+ APPL_TRACE_DEBUG1("bta_dm_is_sco_active: SCO active: %d", bScoActive);
+ return bScoActive;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_hid_check
+**
+** Description Disables/Enables sniff in link policy based on SCO Up/Down
+**
+** Returns None
+**
+*******************************************************************************/
+
+static void bta_dm_pm_hid_check(BOOLEAN bScoActive)
+{
+ int j;
+
+ /* if HID is active, disable the link policy */
+ for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+ {
+ /* check if an entry already present */
+ if(bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_HH )
+ {
+ APPL_TRACE_DEBUG2 ("SCO status change(Active: %d), modify HID link policy. state: %d",
+ bScoActive, bta_dm_conn_srvcs.conn_srvc[j].state);
+ bta_dm_pm_set_sniff_policy( bta_dm_find_peer_device(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr), bScoActive);
+
+ /* if we had disabled link policy, seems like the hid device stop retrying SNIFF after a few tries. force sniff if needed */
+ if (!bScoActive)
+ bta_dm_pm_set_mode(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, FALSE);
+ }
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_pm_set_sniff_policy
+**
+** Description Disables/Enables sniff in link policy for the give device
+**
+** Returns None
+**
+*******************************************************************************/
+static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable)
+{
+ UINT16 policy_setting;
+
+ if (!p_dev)
+ return;
+
+ if (bDisable)
+ {
+ policy_setting = bta_dm_cb.cur_policy &
+ (HCI_ENABLE_MASTER_SLAVE_SWITCH |
+ HCI_ENABLE_HOLD_MODE |
+ HCI_ENABLE_PARK_MODE);
+
+ }
+ else
+ {
+ /* allow sniff after sco is closed */
+ policy_setting= bta_dm_cb.cur_policy;
+ }
+
+ /* if disabling SNIFF, make sure link is Active */
+ if (bDisable)
+ bta_dm_pm_active(p_dev->peer_bdaddr);
+
+ /* update device record and set link policy */
+ p_dev->link_policy = policy_setting;
+ BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting);
+
+}
diff --git a/bta/dm/bta_dm_sco.c b/bta/dm/bta_dm_sco.c
new file mode 100644
index 0000000..803242b
--- /dev/null
+++ b/bta/dm/bta_dm_sco.c
@@ -0,0 +1,695 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the down sampling utility to convert PCM samples in
+ * 16k/32k/48k/44.1k/22050/11025 sampling rate into 8K/16bits samples
+ * required for SCO channel format. One API function isprovided and only
+ * possible to be used when transmitting SCO data is sent via HCI
+ * interface.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+
+#ifndef BTA_DM_SCO_DEBUG
+#define BTA_DM_SCO_DEBUG FALSE
+#endif
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_DM_PCM_OVERLAP_SIZE 48
+
+#define BTA_DM_PCM_SMPL_RATE_44100 44100
+#define BTA_DM_PCM_SMPL_RATE_22050 22050
+#define BTA_DM_PCM_SMPL_RATE_11025 11025
+
+/*****************************************************************************
+** Data types for PCM Resampling utility
+*****************************************************************************/
+
+typedef INT32 (*PCONVERT_TO_BT_FILTERED) (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+ UINT32 dwSrcSps,INT32 *pLastCurPos, UINT8 *pOverlapArea);
+typedef INT32 (*PCONVERT_TO_BT_NOFILTER) (void *pSrc, void *pDst, UINT32 dwSrcSamples,
+ UINT32 dwSrcSps);
+typedef struct
+{
+ UINT8 overlap_area[BTA_DM_PCM_OVERLAP_SIZE * 4];
+ UINT32 cur_pos; /* current position */
+ UINT32 src_sps; /* samples per second (source audio data) */
+ PCONVERT_TO_BT_FILTERED filter; /* the action function to do the
+ conversion 44100, 22050, 11025*/
+ PCONVERT_TO_BT_NOFILTER nofilter; /* the action function to do
+ the conversion 48000, 32000, 16000*/
+ UINT32 bits; /* number of bits per pcm sample */
+ UINT32 n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */
+ UINT32 sample_size;
+ UINT32 can_be_filtered;
+ UINT32 divisor;
+} tBTA_DM_PCM_RESAMPLE_CB;
+
+tBTA_DM_PCM_RESAMPLE_CB bta_dm_pcm_cb;
+
+/*****************************************************************************
+** Macro Definition
+*****************************************************************************/
+
+
+#define CHECK_SATURATION16(x) \
+ if (x > 32767) \
+ x = 32767; \
+ else if (x < -32768) \
+ x = -32768;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_44100_TO_BLUETOOTH(pStart, pEnd) \
+ { \
+ INT32 out1, out2, out3, out4, out5; \
+ SRC_TYPE *pS = (SRC_TYPE *)pStart; \
+ SRC_TYPE *pSEnd = (SRC_TYPE *)pEnd; \
+ \
+ while (pS < pSEnd) \
+ { \
+ CurrentPos -= 8000; \
+ \
+ if (CurrentPos >= 0) \
+ { \
+ pS += SRC_CHANNELS; \
+ continue; \
+ } \
+ CurrentPos += dwSrcSps; \
+ \
+ out1 = (SRC_SAMPLE(0) * 1587) \
+ + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 1522) \
+ + ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1337) \
+ + ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 1058); \
+ \
+ out1 = out1 / 30000; \
+ \
+ out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 725) \
+ + ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 384) \
+ + ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 79); \
+ \
+ out2 = out2 / 30000; \
+ \
+ out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 156) \
+ + ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 298) \
+ + ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 345); \
+ \
+ out3 = out3 / 30000; \
+ \
+ out4 = ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 306) \
+ + ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 207) \
+ + ((SRC_SAMPLE(12) + SRC_SAMPLE(-12)) * 78); \
+ \
+ out4 = out4 / 30000; \
+ \
+ out5 = out1 + out2 - out3 - out4; \
+ \
+ CHECK_SATURATION16(out5); \
+ *psBtOut++ = (INT16)out5; \
+ \
+ pS += SRC_CHANNELS; \
+ } \
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_22050_TO_BLUETOOTH(pStart, pEnd) \
+ { \
+ INT32 out1, out2, out3, out4, out5; \
+ SRC_TYPE *pS = (SRC_TYPE *)pStart; \
+ SRC_TYPE *pSEnd = (SRC_TYPE *)pEnd; \
+ \
+ while (pS < pSEnd) \
+ { \
+ CurrentPos -= 8000; \
+ \
+ if (CurrentPos >= 0) \
+ { \
+ pS += SRC_CHANNELS; \
+ continue; \
+ } \
+ CurrentPos += dwSrcSps; \
+ \
+ out1 = (SRC_SAMPLE(0) * 2993) \
+ + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2568) \
+ + ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1509) \
+ + ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 331); \
+ \
+ out1 = out1 / 30000; \
+ \
+ out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 454) \
+ + ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 620) \
+ + ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 305); \
+ \
+ out2 = out2 / 30000; \
+ \
+ out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 127) \
+ + ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 350) \
+ + ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 265) \
+ + ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 6); \
+ \
+ out3 = out3 / 30000; \
+ \
+ out4 = ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 201); \
+ \
+ out4 = out4 / 30000; \
+ \
+ out5 = out1 - out2 + out3 - out4; \
+ \
+ CHECK_SATURATION16(out5); \
+ *psBtOut++ = (INT16)out5; \
+ \
+ pS += SRC_CHANNELS; \
+ } \
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_11025_TO_BLUETOOTH(pStart, pEnd) \
+ { \
+ INT32 out1; \
+ SRC_TYPE *pS = (SRC_TYPE *)pStart; \
+ SRC_TYPE *pSEnd = (SRC_TYPE *)pEnd; \
+ \
+ while (pS < pSEnd) \
+ { \
+ CurrentPos -= 8000; \
+ \
+ if (CurrentPos >= 0) \
+ { \
+ pS += SRC_CHANNELS; \
+ continue; \
+ } \
+ CurrentPos += dwSrcSps; \
+ \
+ out1 = (SRC_SAMPLE(0) * 6349) \
+ + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2874) \
+ - ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1148) \
+ - ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 287) \
+ + ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 675) \
+ - ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 258) \
+ - ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 206) \
+ + ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 266); \
+ \
+ out1 = out1 / 30000; \
+ \
+ CHECK_SATURATION16(out1); \
+ *psBtOut++ = (INT16)out1; \
+ \
+ pS += SRC_CHANNELS; \
+ } \
+ }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef SRC_CHANNELS
+#undef SRC_SAMPLE
+#undef SRC_TYPE
+
+#define SRC_TYPE UINT8
+#define SRC_CHANNELS 1
+#define SRC_SAMPLE(x) ((pS[x] - 0x80) << 8)
+
+/*****************************************************************************
+** Local Function
+*****************************************************************************/
+INT32 Convert_8M_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+ UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+ INT32 CurrentPos = *pLastCurPos;
+ SRC_TYPE *pIn, *pInEnd;
+ SRC_TYPE *pOv, *pOvEnd;
+ INT16 *psBtOut = (INT16 *)pDst;
+#if BTA_DM_SCO_DEBUG
+ APPL_TRACE_DEBUG1("Convert_8M_ToBT_Filtered, CurrentPos %d\n", CurrentPos);
+#endif
+ memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+ pOv = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+ pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+ pIn = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+ pInEnd = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+ BTA_DM_PCM_OVERLAP_SIZE);
+
+ if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+ {
+ CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+ }
+ else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+ {
+ CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+ }
+ else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+ {
+ CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+ }
+
+ memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+ (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+ *pLastCurPos = CurrentPos;
+
+ return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_8M_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+ INT32 CurrentPos;
+ UINT8 *pbSrc = (UINT8 *)pSrc;
+ INT16 *psDst = (INT16 *)pDst;
+ INT16 sWorker;
+
+ // start at dwSpsSrc / 2, decrement by 8000
+ //
+ CurrentPos = (dwSrcSps >> 1);
+
+ while (dwSrcSamples--)
+ {
+ CurrentPos -= 8000;
+
+ if (CurrentPos >= 0)
+ pbSrc++;
+ else
+ {
+ sWorker = *pbSrc++;
+ sWorker -= 0x80;
+ sWorker <<= 8;
+
+ *psDst++ = sWorker;
+
+ CurrentPos += dwSrcSps;
+ }
+ }
+
+ return (psDst - (INT16 *)pDst);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef SRC_CHANNELS
+#undef SRC_SAMPLE
+#undef SRC_TYPE
+
+#define SRC_TYPE INT16
+#define SRC_CHANNELS 1
+#define SRC_SAMPLE(x) pS[x]
+
+INT32 Convert_16M_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+ UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+ INT32 CurrentPos = *pLastCurPos;
+ SRC_TYPE *pIn, *pInEnd;
+ SRC_TYPE *pOv, *pOvEnd;
+ INT16 *psBtOut = (INT16 *)pDst;
+
+ memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+ pOv = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+ pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+ pIn = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+ pInEnd = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+ if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+ {
+ CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+ }
+ else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+ {
+ CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+ }
+ else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+ {
+ CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+ }
+
+ memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+ (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+ *pLastCurPos = CurrentPos;
+
+ return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_16M_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+ INT32 CurrentPos;
+ INT16 *psSrc = (INT16 *)pSrc;
+ INT16 *psDst = (INT16 *)pDst;
+
+ // start at dwSpsSrc / 2, decrement by 8000
+ //
+ CurrentPos = (dwSrcSps >> 1);
+
+ while (dwSrcSamples--)
+ {
+ CurrentPos -= 8000;
+
+ if (CurrentPos >= 0)
+ psSrc++;
+ else
+ {
+ *psDst++ = *psSrc++;
+
+ CurrentPos += dwSrcSps;
+ }
+ }
+
+ return (psDst - (INT16 *)pDst);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef SRC_CHANNELS
+#undef SRC_SAMPLE
+#undef SRC_TYPE
+
+#define SRC_TYPE UINT8
+#define SRC_CHANNELS 2
+#define SRC_SAMPLE(x) ((((pS[x * 2] - 0x80) << 8) + ((pS[(x * 2) + 1] - 0x80) << 8)) >> 1)
+
+INT32 Convert_8S_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+ UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+ INT32 CurrentPos = *pLastCurPos;
+ SRC_TYPE *pIn, *pInEnd;
+ SRC_TYPE *pOv, *pOvEnd;
+ INT16 *psBtOut = (INT16 *)pDst;
+
+#if BTA_DM_SCO_DEBUG
+ APPL_TRACE_DEBUG5("Convert_8S_ToBT_Filtered CurrentPos %d, SRC_TYPE %d, SRC_CHANNELS %d, \
+ dwSrcSamples %d, dwSrcSps %d", CurrentPos, sizeof (SRC_TYPE), SRC_CHANNELS, \
+ dwSrcSamples, dwSrcSps);
+#endif
+ memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+ pOv = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+ pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+ pIn = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+ pInEnd = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+ if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+ {
+ CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+ }
+ else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+ {
+ CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+ }
+ else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+ {
+ CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+ }
+
+ memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+ (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+ *pLastCurPos = CurrentPos;
+
+ return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_8S_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+ INT32 CurrentPos;
+ UINT8 *pbSrc = (UINT8 *)pSrc;
+ INT16 *psDst = (INT16 *)pDst;
+ INT16 sWorker, sWorker2;
+
+ // start at dwSpsSrc / 2, decrement by 8000
+ //
+ CurrentPos = (dwSrcSps >> 1);
+
+ while (dwSrcSamples--)
+ {
+ CurrentPos -= 8000;
+
+ if (CurrentPos >= 0)
+ pbSrc += 2;
+ else
+ {
+ sWorker = *(unsigned char *)pbSrc;
+ sWorker -= 0x80;
+ sWorker <<= 8;
+ pbSrc++;
+
+ sWorker2 = *(unsigned char *)pbSrc;
+ sWorker2 -= 0x80;
+ sWorker2 <<= 8;
+ pbSrc++;
+
+ sWorker += sWorker2;
+ sWorker >>= 1;
+
+ *psDst++ = sWorker;
+
+ CurrentPos += dwSrcSps;
+ }
+ }
+
+ return (psDst - (INT16 *)pDst);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef SRC_CHANNELS
+#undef SRC_SAMPLE
+#undef SRC_TYPE
+
+#define SRC_TYPE INT16
+#define SRC_CHANNELS 2
+#define SRC_SAMPLE(x) ((pS[x * 2] + pS[(x * 2) + 1]) >> 1)
+
+INT32 Convert_16S_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+ UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+ INT32 CurrentPos = *pLastCurPos;
+ SRC_TYPE *pIn, *pInEnd;
+ SRC_TYPE *pOv, *pOvEnd;
+ INT16 *psBtOut = (INT16 *)pDst;
+
+ memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+ pOv = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+ pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+ pIn = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+ pInEnd = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+ if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+ {
+ CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+ }
+ else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+ {
+ CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+ }
+ else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+ {
+ CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+ CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+ }
+
+ memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+ (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+ *pLastCurPos = CurrentPos;
+
+ return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_16S_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+ INT32 CurrentPos;
+ INT16 *psSrc = (INT16 *)pSrc;
+ INT16 *psDst = (INT16 *)pDst;
+ INT16 sWorker;
+
+ // start at dwSpsSrc / 2, decrement by 8000
+ //
+ CurrentPos = (dwSrcSps >> 1);
+
+ while (dwSrcSamples--)
+ {
+ CurrentPos -= 8000;
+
+ if (CurrentPos >= 0)
+ psSrc += 2;
+ else
+ {
+ /* CR 82894, to avoid overflow, divide before add */
+ sWorker = ((*psSrc) >> 1 );
+ psSrc++;
+ sWorker += ((*psSrc) >> 1 );
+ psSrc++;
+
+ *psDst++ = sWorker;
+
+ CurrentPos += dwSrcSps;
+ }
+ }
+
+ return (psDst - (INT16 *)pDst);
+}
+
+/*******************************************************************************
+**
+** Function BTA_DmPcmInitSamples
+**
+** Description initialize the down sample converter.
+**
+** src_sps: original samples per second (source audio data)
+** (ex. 44100, 48000)
+** bits: number of bits per pcm sample (16)
+** n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns none
+**
+*******************************************************************************/
+void BTA_DmPcmInitSamples (UINT32 src_sps, UINT32 bits, UINT32 n_channels)
+{
+ tBTA_DM_PCM_RESAMPLE_CB *p_cb = &bta_dm_pcm_cb;
+
+ p_cb->cur_pos = src_sps / 2;
+ p_cb->src_sps = src_sps;
+ p_cb->bits = bits;
+ p_cb->n_channels = n_channels;
+ p_cb->sample_size = 2;
+ p_cb->divisor = 2;
+
+ memset(p_cb->overlap_area, 0, sizeof(p_cb->overlap_area) );
+
+ if ((src_sps == BTA_DM_PCM_SMPL_RATE_44100) ||
+ (src_sps == BTA_DM_PCM_SMPL_RATE_22050) ||
+ (src_sps == BTA_DM_PCM_SMPL_RATE_11025))
+ p_cb->can_be_filtered = 1;
+ else
+ p_cb->can_be_filtered = 0;
+
+#if BTA_DM_SCO_DEBUG
+ APPL_TRACE_DEBUG2("bta_dm_pcm_init_samples: n_channels = %d bits = %d", n_channels, bits);
+#endif
+ if(n_channels == 1)
+ {
+ /* mono */
+ if(bits == 8)
+ {
+ p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_8M_ToBT_Filtered;
+ p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_8M_ToBT_NoFilter;
+ p_cb->divisor = 1;
+ }
+ else
+ {
+ p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_16M_ToBT_Filtered;
+ p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_16M_ToBT_NoFilter;
+ }
+ }
+ else
+ {
+ /* stereo */
+ if(bits == 8)
+ {
+ p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_8S_ToBT_Filtered;
+ p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_8S_ToBT_NoFilter;
+ }
+ else
+ {
+ p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_16S_ToBT_Filtered;
+ p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_16S_ToBT_NoFilter;
+ p_cb->divisor = 4;
+ }
+ }
+
+#if BTA_DM_SCO_DEBUG
+ APPL_TRACE_DEBUG2("bta_pcm_init_dwn_sample: cur_pos %d, src_sps %d", \
+ p_cb->cur_pos, p_cb->src_sps);
+ APPL_TRACE_DEBUG3("bta_pcm_init_dwn_sample: bits %d, n_channels %d, sample_size %d, ", \
+ p_cb->bits, p_cb->n_channels, p_cb->sample_size);
+ APPL_TRACE_DEBUG3("bta_pcm_init_dwn_sample: can_be_filtered %d, n_channels: %d, \
+ divisor %d", p_cb->can_be_filtered, p_cb->n_channels, p_cb->divisor);
+#endif
+
+}
+
+/**************************************************************************************
+** Function BTA_DmPcmResample
+**
+** Description Down sampling utility to convert higher sampling rate into 8K/16bits
+** PCM samples.
+**
+** Parameters p_src: pointer to the buffer where the original sampling PCM
+** are stored.
+** in_bytes: Length of the input PCM sample buffer in byte.
+** p_dst: pointer to the buffer which is to be used to store
+** the converted PCM samples.
+**
+**
+** Returns INT32: number of samples converted.
+**
+**************************************************************************************/
+INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst)
+{
+ UINT32 out_sample;
+
+#if BTA_DM_SCO_DEBUG
+ APPL_TRACE_DEBUG1("bta_pcm_resample : insamples %d", (in_bytes / bta_dm_pcm_cb.divisor));
+#endif
+ if(bta_dm_pcm_cb.can_be_filtered)
+ {
+ out_sample = (*bta_dm_pcm_cb.filter) (p_src, p_dst, (in_bytes / bta_dm_pcm_cb.divisor),
+ bta_dm_pcm_cb.src_sps, (INT32 *) &bta_dm_pcm_cb.cur_pos, bta_dm_pcm_cb.overlap_area);
+ }
+ else
+ {
+ out_sample = (*bta_dm_pcm_cb.nofilter) (p_src, p_dst,
+ (in_bytes / bta_dm_pcm_cb.divisor), bta_dm_pcm_cb.src_sps);
+ }
+
+#if BTA_DM_SCO_DEBUG
+ APPL_TRACE_DEBUG1("bta_pcm_resample : outsamples %d", out_sample);
+#endif
+
+ return (out_sample * bta_dm_pcm_cb.sample_size);
+}
+#endif
diff --git a/bta/fs/bta_fs_cfg.c b/bta/fs/bta_fs_cfg.c
new file mode 100644
index 0000000..0bfffcd
--- /dev/null
+++ b/bta/fs/bta_fs_cfg.c
@@ -0,0 +1,51 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains compile-time configurable constants for the BTA File
+ * System.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "bta_fs_api.h"
+
+/* Character used as path separator */
+#ifndef BTA_FS_PATH_SEPARATOR
+#define BTA_FS_PATH_SEPARATOR ((char) 0x2f) /* 0x2f ('/'), or 0x5c ('\') */
+#endif
+
+/* Maximum path length supported by MMI */
+#ifndef BTA_FS_PATH_LEN
+#define BTA_FS_PATH_LEN 294
+#endif
+
+#ifndef BTA_FS_FILE_LEN
+#define BTA_FS_FILE_LEN 256
+#endif
+
+const tBTA_FS_CFG bta_fs_cfg =
+{
+ BTA_FS_FILE_LEN,
+ BTA_FS_PATH_LEN,
+ BTA_FS_PATH_SEPARATOR
+};
+
+tBTA_FS_CFG *p_bta_fs_cfg = (tBTA_FS_CFG *)&bta_fs_cfg;
+
diff --git a/bta/fs/bta_fs_ci.c b/bta/fs/bta_fs_ci.c
new file mode 100644
index 0000000..589a591
--- /dev/null
+++ b/bta/fs/bta_fs_ci.c
@@ -0,0 +1,280 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation file for the file system call-in functions.
+ *
+ ******************************************************************************/
+#include <string.h>
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_fs_ci.h"
+#include "gki.h"
+#include "bd.h"
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_write
+**
+** Description This function sends an event to IO indicating the phone
+** has written the number of bytes specified in the call-out
+** function, bta_fs_co_write(), and is ready for more data.
+** This function is used to control the TX data flow.
+** Note: The data buffer is released by the stack after
+** calling this function.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_fs_ci_open call-in function.
+** status - BTA_FS_CO_OK or BTA_FS_CO_FAIL
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fs_ci_write(int fd, tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+ tBTA_FS_CI_WRITE_EVT *p_evt;
+
+ if ((p_evt = (tBTA_FS_CI_WRITE_EVT *) GKI_getbuf(sizeof(tBTA_FS_CI_WRITE_EVT))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->fd = fd;
+ p_evt->status = status;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_read
+**
+** Description This function sends an event to BTA indicating the phone has
+** read in the requested amount of data specified in the
+** bta_fs_co_read() call-out function. It should only be called
+** when the requested number of bytes has been read in, or after
+** the end of the file has been detected.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_fs_ci_open call-in function.
+** num_bytes_read - number of bytes read into the buffer
+** specified in the read callout-function.
+** status - BTA_FS_CO_OK if full buffer of data,
+** BTA_FS_CO_EOF if the end of file has been reached,
+** BTA_FS_CO_FAIL if an error has occurred.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fs_ci_read(int fd, UINT16 num_bytes_read, tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+ tBTA_FS_CI_READ_EVT *p_evt;
+
+ if ((p_evt = (tBTA_FS_CI_READ_EVT *) GKI_getbuf(sizeof(tBTA_FS_CI_READ_EVT))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->fd = fd;
+ p_evt->status = status;
+ p_evt->num_read = num_bytes_read;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_open
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished opening a file for reading or writing.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_fs_ci_open call-in function.
+** status - BTA_FS_CO_OK if file was opened in mode specified
+** in the call-out function.
+** BTA_FS_CO_EACCES if the file exists, but contains
+** the wrong access permissions.
+** BTA_FS_CO_FAIL if any other error has occurred.
+** file_size - The total size of the file
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fs_ci_open(int fd, tBTA_FS_CO_STATUS status, UINT32 file_size, UINT16 evt)
+{
+ tBTA_FS_CI_OPEN_EVT *p_evt;
+
+ if ((p_evt = (tBTA_FS_CI_OPEN_EVT *) GKI_getbuf(sizeof(tBTA_FS_CI_OPEN_EVT))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->fd = fd;
+ p_evt->status = status;
+ p_evt->file_size = file_size;
+ p_evt->p_file = NULL;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_direntry
+**
+** Description This function is called in response to the
+** bta_fs_co_getdirentry call-out function.
+**
+** Parameters status - BTA_FS_CO_OK if p_entry points to a valid entry.
+** BTA_FS_CO_EODIR if no more entries (p_entry is ignored).
+** BTA_FS_CO_FAIL if any errors have occurred.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fs_ci_direntry(tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+ tBTA_FS_CI_GETDIR_EVT *p_evt;
+
+ if ((p_evt = (tBTA_FS_CI_GETDIR_EVT *)GKI_getbuf(sizeof(tBTA_FS_CI_GETDIR_EVT))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_resume
+**
+** Description This function is called in response to the
+** bta_fs_co_resume call-out function.
+**
+** Parameters p_sess_info - the stored session ID and related information.
+** timeout - the timeout for this suspended session.
+** ssn - the stored session sequence number.
+** info - the stored BTA specific information (like last active operation).
+** status - BTA_FS_CO_OK if p_entry points to a valid entry.
+** BTA_FS_CO_FAIL if any errors have occurred.
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fs_ci_resume (BD_ADDR_PTR p_addr, UINT8 *p_sess_info,
+ UINT32 timeout, UINT32 offset, UINT8 ssn, UINT8 info,
+ tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+ tBTA_FS_CI_RESUME_EVT *p_evt;
+ UINT16 size = sizeof(tBTA_FS_CI_RESUME_EVT) + sizeof(BD_ADDR);
+
+ if ((p_evt = (tBTA_FS_CI_RESUME_EVT *)GKI_getbuf(size)) != NULL)
+ {
+ p_evt->p_addr = NULL;
+ if (p_addr != NULL)
+ {
+ p_evt->p_addr = (BD_ADDR_PTR)(p_evt + 1);
+ bdcpy(p_evt->p_addr, p_addr);
+ }
+ p_evt->hdr.event = evt;
+ p_evt->p_sess_info = p_sess_info;
+ p_evt->timeout = timeout;
+ p_evt->offset = offset;
+ p_evt->ssn = ssn;
+ p_evt->info = info;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_action
+**
+** Description This function is called in response to one of the action
+** call-out functions: bta_fs_co_copy, bta_fs_co_rename or
+** bta_fs_co_set_perms.
+**
+** Parameters status - BTA_FS_CO_OK if the action is succession.
+** BTA_FS_CO_FAIL if any errors have occurred.
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fs_ci_action(tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+ tBTA_FS_CI_ACTION_EVT *p_evt;
+
+ if ((p_evt = (tBTA_FS_CI_ACTION_EVT *) GKI_getbuf(sizeof(tBTA_FS_CI_ACTION_EVT))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->status = status;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_resume_op
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished opening a file for reading or writing on resume.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_fs_ci_open call-in function.
+** status - BTA_FS_CO_OK if file was opened in mode specified
+** in the call-out function.
+** BTA_FS_CO_EACCES if the file exists, but contains
+** the wrong access permissions.
+** BTA_FS_CO_FAIL if any other error has occurred.
+** p_file - The file name associated with fd
+** file_size - The total size of the file
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fs_ci_resume_op(int fd, tBTA_FS_CO_STATUS status, const char *p_file,
+ UINT32 file_size, UINT16 evt)
+{
+ tBTA_FS_CI_OPEN_EVT *p_evt;
+ UINT16 file_len = strlen(p_file) + 1;
+ UINT16 size = sizeof(tBTA_FS_CI_OPEN_EVT) + file_len;
+ char *p;
+
+ if ((p_evt = (tBTA_FS_CI_OPEN_EVT *) GKI_getbuf(size)) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->fd = fd;
+ p_evt->status = status;
+ p_evt->file_size = file_size;
+ p = (char *)(p_evt + 1);
+ BCM_STRNCPY_S (p, file_len, p_file, file_len-1);
+ p[file_len] = '\0';
+ p_evt->p_file = (const char *)p;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
new file mode 100644
index 0000000..5cacf03
--- /dev/null
+++ b/bta/gatt/bta_gattc_act.c
@@ -0,0 +1,1802 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the GATT client action functions for the state
+ * machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+
+#include "utl.h"
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+
+#include "bta_gattc_int.h"
+#include "l2c_api.h"
+
+
+#include <string.h>
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason);
+
+static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+ tGATT_CL_COMPLETE *p_data);
+
+static tGATT_CBACK bta_gattc_cl_cback =
+{
+ bta_gattc_conn_cback,
+ bta_gattc_cmpl_cback,
+ bta_gattc_disc_res_cback,
+ bta_gattc_disc_cmpl_cback,
+ NULL
+};
+
+/* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */
+static UINT16 bta_gattc_opcode_to_int_evt[] =
+{
+ BTA_GATTC_API_READ_EVT,
+ BTA_GATTC_API_WRITE_EVT,
+ BTA_GATTC_API_EXEC_EVT
+};
+
+#if (BT_TRACE_VERBOSE == TRUE)
+static const char *bta_gattc_op_code_name[] =
+{
+ "Unknown",
+ "Discovery",
+ "Read",
+ "Write",
+ "Exec",
+ "Config",
+ "Notification",
+ "Indication"
+};
+#endif
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_gattc_register
+**
+** Description Register a GATT client application with BTA.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC cb_data;
+ UINT8 i;
+ tBT_UUID *p_app_uuid = &p_data->api_reg.app_uuid;
+ tBTA_GATTC_INT_START_IF *p_buf;
+
+
+ /* todo need to check duplicate uuid */
+ for (i = 0; i < BTA_GATTC_CL_MAX; i ++)
+ {
+ if (!p_cb->cl_rcb[i].in_use)
+ {
+ if ((p_app_uuid == NULL) || (p_cb->cl_rcb[i].client_if = GATT_Register(p_app_uuid, &bta_gattc_cl_cback)) == 0)
+ {
+ APPL_TRACE_ERROR0("Register with GATT stack failed.");
+ cb_data.reg_oper.status = BTA_GATT_ERROR;
+ }
+ else
+
+ {
+ p_cb->cl_rcb[i].in_use = TRUE;
+ p_cb->cl_rcb[i].p_cback = p_data->api_reg.p_cback;
+ memcpy(&p_cb->cl_rcb[i].app_uuid, p_app_uuid, sizeof(tBT_UUID));
+
+ /* BTA use the same client interface as BTE GATT statck */
+ cb_data.reg_oper.client_if = p_cb->cl_rcb[i].client_if;
+// btla-specific ++
+ memcpy(&(cb_data.reg_oper.app_uuid),p_app_uuid,sizeof(tBT_UUID));
+// btla-specific --
+
+ cb_data.reg_oper.status = BTA_GATT_OK;
+
+ if ((p_buf = (tBTA_GATTC_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTC_INT_START_IF))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTC_INT_START_IF_EVT;
+ p_buf->client_if = p_cb->cl_rcb[i].client_if;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ else
+ {
+ cb_data.reg_oper.status = BTA_GATT_NO_RESOURCES;
+ memset( &p_cb->cl_rcb[i], 0 , sizeof(tBTA_GATTC_RCB));
+ }
+ break;
+ }
+ }
+ }
+ /* callback with register event */
+ if (p_data->api_reg.p_cback)
+ {
+ (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT, (tBTA_GATTC *)&cb_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_start_if
+**
+** Description start an application interface.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
+{
+ if (bta_gattc_cl_get_regcb(p_msg->int_start_if.client_if) !=NULL )
+ {
+ GATT_StartIf(p_msg->int_start_if.client_if);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.client_if );
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gattc_deregister_cmpl
+**
+** Description De-Register a GATT client application with BTA completed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_int_deregister_cmpl(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_IF client_if)
+{
+ tBTA_GATTC_CBACK *p_cback = p_clreg->p_cback;
+ tBTA_GATTC cb_data;
+
+
+ APPL_TRACE_DEBUG1("bta_gattc_int_deregister_cmpl client_if=%d", client_if );
+
+ GATT_Deregister(p_clreg->client_if);
+ memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB));
+
+ cb_data.reg_oper.client_if = client_if;
+ cb_data.reg_oper.status = BTA_GATT_OK;
+
+ if (p_cback)
+ /* callback with de-register event */
+ (*p_cback)(BTA_GATTC_DEREG_EVT, (tBTA_GATTC *)&cb_data);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gattc_deregister_cmpl
+**
+** Description De-Register a GATT client application with BTA completed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_IF client_if)
+{
+ tBTA_GATTC_INT_DEREG *p_buf;
+
+ APPL_TRACE_DEBUG1("bta_gattc_deregister_cmpl client_if=%d", client_if );
+
+ if ((p_buf = (tBTA_GATTC_INT_DEREG *) GKI_getbuf(sizeof(tBTA_GATTC_INT_DEREG))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTC_INT_DEREG_EVT;
+ p_buf->client_if = client_if;
+ bta_sys_sendmsg(p_buf);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_gattc_deregister_cmpl unable to allocate buffer to complete dereg=%d", client_if);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_deregister
+**
+** Description De-Register a GATT client application with BTA.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_int_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
+{
+
+ tBTA_GATTC_IF client_if = p_data->int_dereg.client_if;
+ tBTA_GATTC_CBACK *p_cback;
+ tBTA_GATTC cb_data;
+ tBTA_GATTC_RCB *p_clreg;
+
+
+ APPL_TRACE_DEBUG1("bta_gattc_int_deregister_cmpl client_if=%d", client_if );
+
+ if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
+ {
+ p_cback = p_clreg->p_cback;
+ GATT_Deregister(client_if);
+ memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB));
+ cb_data.reg_oper.client_if = client_if;
+ cb_data.reg_oper.status = BTA_GATT_OK;
+
+ if (p_cback)
+ /* callback with de-register event */
+ (*p_cback)(BTA_GATTC_DEREG_EVT, (tBTA_GATTC *)&cb_data);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_gattc_int_deregister Deregister Failed, unknown client_if: %d", p_data->int_dereg.client_if);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gattc_deregister
+**
+** Description De-Register a GATT client application with BTA.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC_RCB *p_clreg;
+ UINT8 i;
+ BT_HDR buf;
+
+ if ((p_clreg = bta_gattc_cl_get_regcb(p_data->api_dereg.client_if)) != NULL)
+ {
+ if (p_clreg->num_clcb > 0)
+ {
+ /* close all CLCB related to this app */
+ for (i= 0; i < BTA_GATTC_CLCB_MAX; i ++)
+ {
+ if (p_cb->clcb[i].in_use && (p_cb->clcb[i].p_rcb == p_clreg))
+ {
+ p_clreg->dereg_pending = TRUE;
+
+ buf.event = BTA_GATTC_API_CLOSE_EVT;
+ buf.layer_specific = p_cb->clcb[i].bta_conn_id;
+ bta_gattc_close(&p_cb->clcb[i], (tBTA_GATTC_DATA *)&buf) ;
+ }
+ }
+ }
+ else
+ bta_gattc_deregister_cmpl(p_clreg, p_clreg->client_if);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_gattc_deregister Deregister Failed, unknown client_if: %d", p_data->api_dereg.client_if);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_process_api_open
+**
+** Description process connect API request.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+ UINT16 event = ((BT_HDR *)p_msg)->event;
+ tBTA_GATTC_CLCB *p_clcb = NULL;
+ tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_conn.client_if);
+
+ if (p_clreg != NULL)
+ {
+ if (p_msg->api_conn.is_direct)
+ {
+ if ((p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if,
+ p_msg->api_conn.remote_bda)) != NULL)
+ {
+ bta_gattc_sm_execute(p_clcb, event, p_msg);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("No resources to open a new connection.");
+
+ bta_gattc_send_open_cback(p_clreg,
+ BTA_GATT_NO_RESOURCES,
+ p_msg->api_conn.remote_bda,
+ BTA_GATT_INVALID_CONN_ID);
+ }
+ }
+ else
+ {
+ bta_gattc_init_bk_conn(&p_msg->api_conn, p_clreg);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_gattc_process_api_open Failed, unknown client_if: %d",
+ p_msg->api_conn.client_if);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_process_api_open_cancel
+**
+** Description process connect API request.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+ UINT16 event = ((BT_HDR *)p_msg)->event;
+ tBTA_GATTC_CLCB *p_clcb = NULL;
+ tBTA_GATTC_RCB *p_clreg;
+ tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+
+ if (p_msg->api_cancel_conn.is_direct)
+ {
+ if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->api_cancel_conn.client_if,
+ p_msg->api_cancel_conn.remote_bda)) != NULL)
+ {
+ bta_gattc_sm_execute(p_clcb, event, p_msg);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("No such connection need to be cancelled");
+
+ p_clreg = bta_gattc_cl_get_regcb(p_msg->api_cancel_conn.client_if);
+
+ if (p_clreg && p_clreg->p_cback)
+ {
+ (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ }
+ }
+ }
+ else
+ {
+ bta_gattc_cancel_bk_conn(&p_msg->api_cancel_conn);
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_cancel_open_error
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATT_STATUS status=BTA_GATT_ERROR;
+
+ if ( p_clcb->p_rcb->p_cback )
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_open_error
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ APPL_TRACE_ERROR0("Connection already opened. wrong state");
+
+ bta_gattc_send_open_cback(p_clcb->p_rcb,
+ BTA_GATT_ALREADY_OPEN,
+ p_clcb->bda,
+ p_clcb->bta_conn_id);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_open_fail
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_open_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ bta_gattc_open_error(p_clcb, p_data);
+ /* open failure, remove clcb */
+ bta_gattc_clcb_dealloc(p_clcb);
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_open
+**
+** Description Process API connection function.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC_DATA gattc_data;
+
+ /* open/hold a connection */
+ if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda, TRUE))
+ {
+ APPL_TRACE_ERROR0("Connection open failure");
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_OPEN_FAIL_EVT, p_data);
+ }
+ else
+ {
+ /* a connected remote device */
+ if (GATT_GetConnIdIfConnected(p_clcb->p_rcb->client_if,
+ p_data->api_conn.remote_bda,
+ &p_clcb->bta_conn_id))
+ {
+ gattc_data.hdr.layer_specific = p_clcb->bta_conn_id;
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
+ }
+ /* else wait for the callback event */
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_init_bk_conn
+**
+** Description Process API Open for a background connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg)
+{
+ tBTA_GATT_STATUS status = BTA_GATT_NO_RESOURCES;
+ UINT16 conn_id;
+ tBTA_GATTC_CLCB *p_clcb;
+ tBTA_GATTC_DATA gattc_data;
+
+ if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE))
+ {
+ /* alwaya call open to hold a connection */
+ if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE))
+ {
+ status = BTA_GATT_ERROR;
+ APPL_TRACE_ERROR0("bta_gattc_init_bk_conn failed");
+ }
+ else
+ {
+ status = BTA_GATT_OK;
+
+ /* if is a connected remote device */
+ if (GATT_GetConnIdIfConnected(p_data->client_if,
+ p_data->remote_bda,
+ &conn_id))
+ {
+ if ((p_clcb = bta_gattc_clcb_alloc(p_data->client_if, p_data->remote_bda)) != NULL)
+ {
+ gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
+
+ /* open connection */
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
+ status = BTA_GATT_OK;
+ }
+ }
+ }
+ }
+
+ /* open failure, report OPEN_EVT */
+ if (status != BTA_GATT_OK)
+ {
+ bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda, BTA_GATT_INVALID_CONN_ID);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_cancel_bk_conn
+**
+** Description Process API Cancel Open for a background connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data)
+{
+ tBTA_GATTC_RCB *p_clreg;
+ tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+
+ /* remove the device from the bg connection mask */
+ if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, FALSE))
+ {
+ if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, FALSE))
+ {
+ status = BTA_GATT_OK;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_gattc_cancel_bk_conn failed");
+ }
+ }
+ p_clreg = bta_gattc_cl_get_regcb(p_data->client_if);
+
+ if (p_clreg && p_clreg->p_cback)
+ {
+ (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ }
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_int_cancel_open_ok
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+ if ( p_clcb->p_rcb->p_cback )
+ {
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ }
+
+ bta_gattc_clcb_dealloc(p_clcb);
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_cancel_open
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATT_STATUS status=BTA_GATT_ERROR;
+
+ if (GATT_CancelConnect(p_clcb->p_rcb->client_if, p_data->api_cancel_conn.remote_bda, TRUE))
+ {
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CANCEL_OPEN_OK_EVT, p_data);
+ }
+ else
+ {
+ if ( p_clcb->p_rcb->p_cback )
+ {
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_conn
+**
+** Description receive connection callback from stack
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC_IF gatt_if;
+ APPL_TRACE_DEBUG1("bta_gattc_conn server cache state=%d",p_clcb->p_srcb->state);
+
+ if (p_data != NULL)
+ {
+ APPL_TRACE_DEBUG1("bta_gattc_conn conn_id=%d",p_data->hdr.layer_specific);
+
+ p_clcb->p_srcb->connected = TRUE;
+ p_clcb->bta_conn_id = p_data->hdr.layer_specific;
+ GATT_GetConnectionInfor(p_data->hdr.layer_specific, &gatt_if, p_clcb->bda);
+
+ /* start database cache if needed */
+ if (p_clcb->p_srcb->p_srvc_cache == NULL)
+ {
+ if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
+ {
+ p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_START_CACHE_EVT, p_data);
+ }
+ else /* cache is building */
+ p_clcb->state = BTA_GATTC_DISCOVER_ST;
+ }
+
+ else
+ {
+ /* a pending service handle change indication */
+ if (p_clcb->p_srcb->srvc_hdl_chg)
+ {
+ p_clcb->p_srcb->srvc_hdl_chg = FALSE;
+ /* start discovery */
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+ }
+ }
+
+ if (p_clcb->p_rcb)
+ {
+ bta_gattc_send_open_cback(p_clcb->p_rcb,
+ BTA_GATT_OK,
+ p_clcb->bda,
+ p_clcb->bta_conn_id);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_close_fail
+**
+** Description close a connection.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC cb_data;
+
+ if ( p_clcb->p_rcb->p_cback )
+ {
+ memset(&cb_data, 0, sizeof(tBTA_GATTC));
+ cb_data.close.client_if = p_clcb->p_rcb->client_if;
+ cb_data.close.conn_id = p_data->hdr.layer_specific;
+ bdcpy(cb_data.close.remote_bda, p_clcb->bda);
+ cb_data.close.status = BTA_GATT_ERROR;
+ cb_data.close.reason = BTA_GATT_CONN_NONE;
+
+
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CLOSE_EVT, &cb_data);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_api_close
+**
+** Description close a GATTC connection.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC_CBACK *p_cback = p_clcb->p_rcb->p_cback;
+ tBTA_GATTC_RCB *p_clreg = p_clcb->p_rcb;
+ tBTA_GATTC cb_data;
+
+ APPL_TRACE_DEBUG1("bta_gattc_close conn_id=%d",p_clcb->bta_conn_id);
+
+ if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT)
+ p_clcb->status = GATT_Disconnect(p_clcb->bta_conn_id);
+
+ cb_data.close.client_if = p_clcb->p_rcb->client_if;
+ cb_data.close.conn_id = p_clcb->bta_conn_id;
+ cb_data.close.status = p_clcb->status;
+ cb_data.close.reason = p_clcb->reason;
+ bdcpy(cb_data.close.remote_bda, p_clcb->bda);
+
+ if (p_clcb->status == BTA_GATT_OK)
+ {
+ /* if the srcb is no longer needed, reset the state */
+ if ( -- p_clcb->p_srcb->num_clcb == 0)
+ {
+ APPL_TRACE_DEBUG0("Update srcb connection status");
+ p_clcb->p_srcb->connected = FALSE;
+ p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
+ }
+
+ bta_gattc_clcb_dealloc(p_clcb);
+ }
+
+ ( * p_cback)(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC *)&cb_data);
+
+ if (-- p_clreg->num_clcb == 0 && p_clreg->dereg_pending)
+ {
+ bta_gattc_deregister_cmpl(p_clreg, p_clreg->client_if);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_reset_discover_st
+**
+** Description when a SRCB finished discovery, tell all related clcb.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb)
+{
+ tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
+ UINT8 i;
+
+ for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++)
+ {
+ if (p_cb->clcb[i].p_srcb == p_srcb)
+ {
+ bta_gattc_sm_execute(&p_cb->clcb[i], BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_set_discover_st
+**
+** Description when a SRCB start discovery, tell all related clcb and set
+** the state.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_set_discover_st(tBTA_GATTC_SERV *p_srcb)
+{
+ tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
+ UINT8 i;
+
+#if BLE_INCLUDED == TRUE
+ L2CA_EnableUpdateBleConnParams(p_srcb->server_bda, FALSE);
+#endif
+ for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++)
+ {
+ if (p_cb->clcb[i].p_srcb == p_srcb)
+ {
+ p_cb->clcb[i].state = BTA_GATTC_DISCOVER_ST;
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_start_discover
+**
+** Description Start a discovery on server.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ /* pending operation, wait until it finishes */
+
+ APPL_TRACE_DEBUG1("bta_gattc_start_discover conn_id=%d",p_clcb->bta_conn_id);
+ if (p_clcb->p_q_cmd != NULL && p_clcb->auto_update == BTA_GATTC_NO_SCHEDULE &&
+ p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
+ {
+ p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
+ p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
+ }
+ else /* no pending operation, start discovery right away */
+ {
+ p_clcb->auto_update = BTA_GATTC_NO_SCHEDULE;
+
+ if (p_clcb->p_srcb != NULL)
+ {
+ /* clear the service change mask */
+ p_clcb->p_srcb->srvc_hdl_chg = FALSE;
+ p_clcb->p_srcb->update_count = 0;
+
+ /* set all srcb related clcb into discovery ST */
+ bta_gattc_set_discover_st(p_clcb->p_srcb);
+
+ if ( bta_gattc_init_cache(p_clcb->p_srcb) ||
+ bta_gattc_discover_pri_service(p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL) != BTA_GATT_OK)
+ {
+ APPL_TRACE_ERROR0("discovery on server failed");
+ bta_gattc_reset_discover_st(p_clcb->p_srcb);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("unknown device, can not start discovery");
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_disc_cmpl
+**
+** Description discovery on server is finished
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC_DATA *p_q_cmd = p_clcb->p_q_cmd;
+ APPL_TRACE_DEBUG1("bta_gattc_disc_cmpl conn_id=%d",p_clcb->bta_conn_id);
+
+#if BLE_INCLUDED == TRUE
+ L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE);
+#endif
+ p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
+
+ /* release pending attribute list buffer */
+ utl_freebuf((void **)&p_clcb->p_srcb->p_srvc_list);
+
+ /* get any queued command to proceed */
+ if (p_q_cmd != NULL)
+ {
+ p_clcb->p_q_cmd = NULL;
+
+ bta_gattc_sm_execute(p_clcb, p_q_cmd->hdr.event, p_q_cmd);
+
+ utl_freebuf((void **)&p_q_cmd);
+
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_read
+**
+** Description Read an attribute
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ UINT16 handle = 0;
+ tGATT_READ_PARAM read_param;
+ tBTA_GATTC_OP_CMPL op_cmpl;
+
+ memset (&read_param, 0 ,sizeof(tGATT_READ_PARAM));
+ memset (&op_cmpl, 0 ,sizeof(tBTA_GATTC_OP_CMPL));
+
+ if (bta_gattc_enqueue(p_clcb, p_data))
+ {
+ if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+ &p_data->api_read.srvc_id,
+ &p_data->api_read.char_id,
+ p_data->api_read.descr_type)) == 0)
+ {
+ op_cmpl.status = BTA_GATT_ERROR;
+ }
+ else
+ {
+ read_param.by_handle.handle = handle;
+ read_param.by_handle.auth_req = p_data->api_read.auth_req;
+
+ op_cmpl.status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_HANDLE, &read_param);
+ }
+
+ /* read fail */
+ if (op_cmpl.status != BTA_GATT_OK)
+ {
+ op_cmpl.op_code = GATTC_OPTYPE_READ;
+ op_cmpl.p_cmpl = NULL;
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_read_multi
+**
+** Description read multiple
+**
+** Returns None.
+*********************************************************************************/
+void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ UINT16 i, handle;
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+ tGATT_READ_PARAM read_param;
+ tBTA_GATTC_OP_CMPL op_cmpl;
+ tBTA_GATTC_ATTR_ID *p_id;
+ tBT_UUID dummy_uuid;
+
+ if (bta_gattc_enqueue(p_clcb, p_data))
+ {
+ memset(&dummy_uuid, 0, sizeof(tBT_UUID));
+ memset(&read_param, 0, sizeof(tGATT_READ_PARAM));
+
+ p_id = p_data->api_read_multi.p_id_list;
+
+ for (i = 0; i < p_data->api_read_multi.num_attr && p_id; i ++, p_id ++)
+ {
+ handle = 0;
+
+ if (p_id->id_type == BTA_GATT_TYPE_CHAR)
+ {
+ handle = bta_gattc_id2handle(p_clcb->p_srcb,
+ &p_id->id_value.char_id.srvc_id,
+ &p_id->id_value.char_id.char_id,
+ dummy_uuid);
+ }
+ else if (p_id->id_type == BTA_GATT_TYPE_CHAR_DESCR)
+ {
+ handle = bta_gattc_id2handle(p_clcb->p_srcb,
+ &p_id->id_value.char_descr_id.char_id.srvc_id,
+ &p_id->id_value.char_descr_id.char_id.char_id,
+ p_id->id_value.char_descr_id.descr_type);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("invalud ID type: %d", p_id->id_type);
+ }
+
+ if (handle == 0)
+ {
+ status = BTA_GATT_ERROR;
+ break;
+ }
+ }
+ if (status == BTA_GATT_OK)
+ {
+ read_param.read_multiple.num_handles = p_data->api_read_multi.num_attr;
+ read_param.read_multiple.auth_req = p_data->api_read_multi.auth_req;
+
+ status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_MULTIPLE, &read_param);
+ }
+
+ /* read fail */
+ if (status != BTA_GATT_OK)
+ {
+ memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL));
+
+ op_cmpl.status = status;
+ op_cmpl.op_code = GATTC_OPTYPE_READ;
+ op_cmpl.p_cmpl = NULL;
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_write
+**
+** Description Write an attribute
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ UINT16 handle = 0;
+ tGATT_VALUE attr = {0};
+ tBTA_GATTC_OP_CMPL op_cmpl;
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+ if (bta_gattc_enqueue(p_clcb, p_data))
+ {
+ if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+ &p_data->api_write.srvc_id,
+ &p_data->api_write.char_id,
+ p_data->api_write.descr_type)) == 0)
+ {
+ status = BTA_GATT_ERROR;
+ }
+ else
+ {
+ attr.handle= handle;
+ attr.offset = p_data->api_write.offset;
+ attr.len = p_data->api_write.len;
+ attr.auth_req = p_data->api_write.auth_req;
+
+ if (p_data->api_write.p_value)
+ memcpy(attr.value, p_data->api_write.p_value, p_data->api_write.len);
+
+ status = GATTC_Write(p_clcb->bta_conn_id, p_data->api_write.write_type, &attr);
+ }
+
+ /* write fail */
+ if (status != BTA_GATT_OK)
+ {
+ memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL));
+
+ op_cmpl.status = status;
+ op_cmpl.op_code = GATTC_OPTYPE_WRITE;
+ op_cmpl.p_cmpl = NULL;
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_execute
+**
+** Description send execute write
+**
+** Returns None.
+*********************************************************************************/
+void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC_OP_CMPL op_cmpl;
+ tBTA_GATT_STATUS status;
+
+ if (bta_gattc_enqueue(p_clcb, p_data))
+ {
+ status = GATTC_ExecuteWrite(p_clcb->bta_conn_id, p_data->api_exec.is_execute);
+
+ if (status != BTA_GATT_OK)
+ {
+ memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL));
+
+ op_cmpl.status = status;
+ op_cmpl.op_code = GATTC_OPTYPE_EXE_WRITE;
+ op_cmpl.p_cmpl = NULL;
+
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_confirm
+**
+** Description send handle value confirmation
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ UINT16 handle;
+ tBT_UUID null_uuid = {0};
+
+ if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+ &p_data->api_confirm.srvc_id,
+ &p_data->api_confirm.char_id,
+ null_uuid)) == 0)
+ {
+ APPL_TRACE_ERROR0("Can not map service/char ID into valid handle");
+ }
+ else
+ {
+ if (GATTC_SendHandleValueConfirm(p_data->api_confirm.hdr.layer_specific, handle)
+ != GATT_SUCCESS)
+ {
+ APPL_TRACE_ERROR1("bta_gattc_confirm to handle [0x%04x] failed", handle);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_read_cmpl
+**
+** Description read complete
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+ UINT8 event;
+ tBTA_GATTC cb_data;
+ tBTA_GATT_READ_VAL read_value;
+
+ memset(&cb_data, 0, sizeof(tBTA_GATTC));
+ memset(&read_value, 0, sizeof(tBTA_GATT_READ_VAL));
+
+ cb_data.read.status = p_data->status;
+
+ if (p_data->p_cmpl != NULL && p_data->status == BTA_GATT_OK)
+ {
+ if (bta_gattc_handle2id(p_clcb->p_srcb,
+ p_data->p_cmpl->att_value.handle,
+ &cb_data.read.srvc_id,
+ &cb_data.read.char_id,
+ &cb_data.read.descr_type) == FALSE)
+ {
+ cb_data.read.status = BTA_GATT_INTERNAL_ERROR;
+ APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", p_data->p_cmpl->att_value.handle);
+ }
+ else
+ {
+ cb_data.read.status = bta_gattc_pack_read_cb_data(p_clcb->p_srcb,
+ cb_data.read.descr_type,
+ &p_data->p_cmpl->att_value,
+ &read_value);
+ cb_data.read.p_value = &read_value;
+ }
+ }
+ else
+ {
+ cb_data.read.srvc_id = p_clcb->p_q_cmd->api_read.srvc_id;
+ cb_data.read.char_id = p_clcb->p_q_cmd->api_read.char_id;
+ cb_data.read.descr_type = p_clcb->p_q_cmd->api_read.descr_type;
+ }
+
+ event = (p_clcb->p_q_cmd->api_read.descr_type.len == 0) ? BTA_GATTC_READ_CHAR_EVT: BTA_GATTC_READ_DESCR_EVT;
+ cb_data.read.conn_id = p_clcb->bta_conn_id;
+
+ utl_freebuf((void **)&p_clcb->p_q_cmd);
+ /* read complete, callback */
+ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_write_cmpl
+**
+** Description read complete
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+ tBTA_GATTC cb_data = {0};
+ UINT8 event;
+
+ cb_data.write.status = p_data->status;
+
+ if (p_data->p_cmpl != NULL)
+ {
+ bta_gattc_handle2id(p_clcb->p_srcb, p_data->p_cmpl->handle,
+ &cb_data.write.srvc_id, &cb_data.write.char_id,
+ &cb_data.write.descr_type);
+ }
+ else
+ {
+ cb_data.write.srvc_id = p_clcb->p_q_cmd->api_write.srvc_id;
+ cb_data.write.char_id = p_clcb->p_q_cmd->api_write.char_id;
+ cb_data.write.descr_type = p_clcb->p_q_cmd->api_write.descr_type;
+ }
+
+ if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT &&
+ p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE)
+
+ event = BTA_GATTC_PREP_WRITE_EVT;
+
+ else if (p_clcb->p_q_cmd->api_write.descr_type.len == 0)
+
+ event = BTA_GATTC_WRITE_CHAR_EVT;
+
+ else
+ event = BTA_GATTC_WRITE_DESCR_EVT;
+
+ utl_freebuf((void **)&p_clcb->p_q_cmd);
+ cb_data.write.conn_id = p_clcb->bta_conn_id;
+ /* write complete, callback */
+ ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_exec_cmpl
+**
+** Description execute write complete
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+ tBTA_GATTC cb_data;
+
+ utl_freebuf((void **)&p_clcb->p_q_cmd);
+
+ p_clcb->status = BTA_GATT_OK;
+
+ /* execute complete, callback */
+ cb_data.exec_cmpl.conn_id = p_clcb->bta_conn_id;
+ cb_data.exec_cmpl.status = p_data->status;
+
+ ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_EXEC_EVT, &cb_data);
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gattc_op_cmpl
+**
+** Description operation completed.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ UINT8 op = (UINT8)p_data->op_cmpl.op_code;
+ UINT8 mapped_op = 0;
+
+ APPL_TRACE_DEBUG1("bta_gattc_op_cmpl op = %d", op);
+
+ if (op == GATTC_OPTYPE_INDICATION || op == GATTC_OPTYPE_NOTIFICATION)
+ {
+ APPL_TRACE_ERROR0("unexpected operation, ignored");
+ }
+ else if (op >= GATTC_OPTYPE_READ)
+ {
+ if (p_clcb->p_q_cmd == NULL)
+ {
+ APPL_TRACE_ERROR0("No pending command");
+ return;
+ }
+ if (p_clcb->p_q_cmd->hdr.event != bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ])
+ {
+ mapped_op = p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT + GATTC_OPTYPE_READ;
+ if ( mapped_op > GATTC_OPTYPE_INDICATION) mapped_op = 0;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+ APPL_TRACE_ERROR3("expect op:(%s :0x%04x), receive unexpected operation (%s).",
+ bta_gattc_op_code_name[mapped_op] , p_clcb->p_q_cmd->hdr.event,
+ bta_gattc_op_code_name[op]);
+#else
+ APPL_TRACE_ERROR3("expect op:(%u :0x%04x), receive unexpected operation (%u).",
+ mapped_op , p_clcb->p_q_cmd->hdr.event, op);
+#endif
+ return;
+ }
+
+ /* service handle change void the response, discard it */
+ if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING)
+ {
+ p_clcb->auto_update = BTA_GATTC_REQ_WAITING;
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+ }
+ else if (op == GATTC_OPTYPE_READ)
+ bta_gattc_read_cmpl(p_clcb, &p_data->op_cmpl);
+
+ else if (op == GATTC_OPTYPE_WRITE)
+ bta_gattc_write_cmpl(p_clcb, &p_data->op_cmpl);
+
+ else if (op == GATTC_OPTYPE_EXE_WRITE)
+ bta_gattc_exec_cmpl(p_clcb, &p_data->op_cmpl);
+ /*
+ else if (op == GATTC_OPTYPE_CONFIG) // API to be added
+ {
+ }
+ */
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_op_cmpl
+**
+** Description operation completed.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ /* receive op complete when discovery is started, ignore the response,
+ and wait for discovery finish and resent */
+ APPL_TRACE_DEBUG1("bta_gattc_ignore_op_cmpl op = %d", p_data->hdr.layer_specific);
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_search
+**
+** Description start a search in the local server cache
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATT_STATUS status = GATT_INTERNAL_ERROR;
+ tBTA_GATTC cb_data;
+ APPL_TRACE_DEBUG1("bta_gattc_search conn_id=%d",p_clcb->bta_conn_id);
+ if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache)
+ {
+ status = BTA_GATT_OK;
+ /* search the local cache of a server device */
+ bta_gattc_search_service(p_clcb, p_data->api_search.srvc_uuid);
+ }
+ cb_data.search_cmpl.status = status;
+ cb_data.search_cmpl.conn_id = p_clcb->bta_conn_id;
+
+ /* end of search or no server cache available */
+ ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_CMPL_EVT, &cb_data);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_q_cmd
+**
+** Description enqueue a command into control block, usually because discovery
+** operation is busy.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ bta_gattc_enqueue(p_clcb, p_data);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_cache_open
+**
+** Description open a NV cache for loading
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ bta_gattc_set_discover_st(p_clcb->p_srcb);
+
+ APPL_TRACE_DEBUG1("bta_gattc_cache_open conn_id=%d",p_clcb->bta_conn_id);
+ bta_gattc_co_cache_open(p_clcb->p_srcb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
+ p_clcb->bta_conn_id, FALSE);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_start_load
+**
+** Description start cache loading by sending callout open cache
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ APPL_TRACE_DEBUG2("bta_gattc_ci_open conn_id=%d server state=%d" ,
+ p_clcb->bta_conn_id, p_clcb->p_srcb->state);
+ if (p_clcb->p_srcb->state == BTA_GATTC_SERV_LOAD)
+ {
+ if (p_data->ci_open.status == BTA_GATT_OK)
+ {
+ p_clcb->p_srcb->attr_index = 0;
+ bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda,
+ BTA_GATTC_CI_CACHE_LOAD_EVT,
+ p_clcb->p_srcb->attr_index,
+ p_clcb->bta_conn_id);
+ }
+ else
+ {
+ /* cache open failure, start discovery */
+ bta_gattc_start_discover(p_clcb, NULL);
+ }
+ }
+ if (p_clcb->p_srcb->state == BTA_GATTC_SERV_SAVE)
+ {
+ if (p_data->ci_open.status == BTA_GATT_OK)
+ {
+ if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id))
+ {
+ p_data->ci_open.status = BTA_GATT_ERROR;
+ }
+ }
+ if (p_data->ci_open.status != BTA_GATT_OK)
+ {
+ p_clcb->p_srcb->attr_index = 0;
+ bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, p_clcb->bta_conn_id);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb);
+
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_ci_load
+**
+** Description cache loading received.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+
+ APPL_TRACE_DEBUG2("bta_gattc_ci_load conn_id=%d load status=%d" ,
+ p_clcb->bta_conn_id, p_data->ci_load.status );
+ bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
+
+ if ((p_data->ci_load.status == BTA_GATT_OK ||
+ p_data->ci_load.status == BTA_GATT_MORE) &&
+ p_data->ci_load.num_attr > 0)
+ {
+ bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr, p_data->ci_load.attr, p_clcb->p_srcb->attr_index);
+
+ if (p_data->ci_load.status == BTA_GATT_OK)
+ {
+ p_clcb->p_srcb->attr_index = 0;
+ bta_gattc_reset_discover_st(p_clcb->p_srcb);
+
+ }
+ else /* load more */
+ {
+ p_clcb->p_srcb->attr_index += p_data->ci_load.num_attr;
+
+ bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda,
+ BTA_GATTC_CI_CACHE_LOAD_EVT,
+ p_clcb->p_srcb->attr_index,
+ p_clcb->bta_conn_id);
+ }
+ }
+ else
+ {
+ p_clcb->p_srcb->attr_index = 0;
+ /* cache open failure, start discovery */
+ bta_gattc_start_discover(p_clcb, NULL);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_ci_load
+**
+** Description cache loading received.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1("bta_gattc_ci_save conn_id=%d " ,
+ p_clcb->bta_conn_id );
+
+ if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id))
+ {
+ p_clcb->p_srcb->attr_index = 0;
+ bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
+ bta_gattc_reset_discover_st(p_clcb->p_srcb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_fail
+**
+** Description report API call failure back to apps
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ if (p_clcb->status == BTA_GATT_OK)
+ {
+ APPL_TRACE_ERROR1("operation not supported at current state [%d]", p_clcb->state);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_conn_cback
+** bta_gattc_cmpl_cback
+**
+** Description callback functions to GATT client stack.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+ BT_HDR *p_buf;
+ tBTA_GATTC_CLCB *p_clcb = NULL;
+
+ APPL_TRACE_DEBUG4("bta_gattc_conn_cback: cif = %d connected = %d conn_id = %d reaosn = 0x%04x",
+ gattc_if, connected, conn_id, reason);
+
+ if (connected)
+ {
+ /* outgoing connection : locate a logic channel */
+ if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda)) == NULL)
+ {
+
+#if BLE_INCLUDED == TRUE
+ /* for a background connection */
+ if (L2CA_GetBleConnRole(bda)== HCI_ROLE_MASTER &&
+ bta_gattc_check_bg_conn(gattc_if, bda))
+ {
+ /* allocate a new channel */
+ p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
+ }
+#endif
+ }
+ if (p_clcb != NULL)
+ {
+ p_clcb->bta_conn_id = conn_id;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_GATTC_INT_CONN_EVT;
+ p_buf->layer_specific = conn_id;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+ }
+ else
+ {
+ /* connection attempt timeout, send connection callback event */
+ if (reason == GATT_CONN_CANCEL )
+ {
+ p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
+ p_clcb->bta_conn_id = conn_id;
+ }
+ if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) != NULL)
+ {
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_GATTC_INT_DISCONN_EVT;
+ p_buf->layer_specific = conn_id;
+ p_clcb->reason = reason;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ }
+ else
+ {
+ APPL_TRACE_DEBUG1(" connection ID: [%d] not used by BTA", conn_id);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_process_srvc_chg_ind
+**
+** Description process service change indication.
+**
+** Returns None.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
+ tBTA_GATTC_RCB *p_clrcb,
+ tBTA_GATTC_SERV *p_srcb,
+ tBTA_GATTC_CLCB *p_clcb,
+ tBTA_GATTC_NOTIFY *p_notify,
+ UINT16 handle)
+{
+ tBT_UUID gattp_uuid, srvc_chg_uuid;
+ BOOLEAN processed = FALSE;
+ UINT8 i;
+
+ gattp_uuid.len = 2;
+ gattp_uuid.uu.uuid16 = UUID_SERVCLASS_GATT_SERVER;
+
+ srvc_chg_uuid.len = 2;
+ srvc_chg_uuid.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD;
+
+ if (bta_gattc_uuid_compare(p_notify->char_id.srvc_id.id.uuid, gattp_uuid, TRUE) &&
+ bta_gattc_uuid_compare(p_notify->char_id.char_id.uuid, srvc_chg_uuid, TRUE))
+ {
+ processed = TRUE;
+ /* mark service handle change pending */
+ p_srcb->srvc_hdl_chg = TRUE;
+ /* clear up all notification/indication registration */
+ bta_gattc_clear_notif_registration(conn_id);
+ /* service change indication all received, do discovery update */
+ if ( ++ p_srcb->update_count == bta_gattc_num_reg_app())
+ {
+ /* not an opened connection; or connection busy */
+ /* search for first available clcb and start discovery */
+ if (p_clcb == NULL || (p_clcb && p_clcb->p_q_cmd != NULL))
+ {
+ for (i = 0 ; i < BTA_GATTC_CLCB_MAX; i ++)
+ {
+ if (bta_gattc_cb.clcb[i].in_use &&
+ bta_gattc_cb.clcb[i].p_srcb == p_srcb &&
+ bta_gattc_cb.clcb[i].p_q_cmd == NULL)
+ {
+ p_clcb = &bta_gattc_cb.clcb[i];
+ break;
+ }
+ }
+ }
+ /* send confirmation here if this is an indication, it should always be */
+ GATTC_SendHandleValueConfirm(conn_id, handle);
+
+ /* if connection available, refresh cache by doing discovery now */
+ if (p_clcb != NULL)
+ bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+ }
+ /* notify applicationf or service change */
+ if (p_clrcb->p_cback != NULL)
+ {
+ APPL_TRACE_ERROR0("bta_gattc_process_srvc_chg_ind 2");
+ (* p_clrcb->p_cback)(BTA_GATTC_SRVC_CHG_EVT, (tBTA_GATTC *)p_srcb->server_bda);
+ }
+
+ }
+
+ return processed;
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_proc_other_indication
+**
+** Description process all non-service change indication/notification.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_proc_other_indication(tBTA_GATTC_CLCB *p_clcb, UINT8 op,
+ tGATT_CL_COMPLETE *p_data,
+ tBTA_GATTC_NOTIFY *p_notify)
+{
+ APPL_TRACE_DEBUG2("bta_gattc_proc_other_indication check \
+ p_data->att_value.handle=%d p_data->handle=%d",
+ p_data->att_value.handle, p_data->handle);
+ APPL_TRACE_DEBUG1("is_notify", p_notify->is_notify);
+
+ p_notify->is_notify = (op == GATTC_OPTYPE_INDICATION) ? FALSE : TRUE;
+ p_notify->len = p_data->att_value.len;
+ bdcpy(p_notify->bda, p_clcb->bda);
+ memcpy(p_notify->value, p_data->att_value.value, p_data->att_value.len);
+ p_notify->conn_id = p_clcb->bta_conn_id;
+
+ if (p_clcb->p_rcb->p_cback)
+ (*p_clcb->p_rcb->p_cback)(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC *)p_notify);
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_process_indicate
+**
+** Description process indication/notification.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPLETE *p_data)
+{
+ UINT16 handle = p_data->att_value.handle;
+ tBTA_GATTC_CLCB *p_clcb ;
+ tBTA_GATTC_RCB *p_clrcb = NULL;
+ tBTA_GATTC_SERV *p_srcb = NULL;
+ tBTA_GATTC_NOTIFY notify;
+ BD_ADDR remote_bda;
+ tBTA_GATTC_IF gatt_if;
+
+ if (!GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda))
+ {
+ APPL_TRACE_ERROR0("indication/notif for unknown app");
+ return;
+ }
+
+ if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) == NULL)
+ {
+ APPL_TRACE_ERROR0("indication/notif for unregistered app");
+ return;
+ }
+
+ if ((p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL)
+ {
+ APPL_TRACE_ERROR0("indication/notif for unknown device, ignore");
+ return;
+ }
+
+ p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+ if (bta_gattc_handle2id(p_srcb, handle,
+ ¬ify.char_id.srvc_id,
+ ¬ify.char_id.char_id,
+ ¬ify.descr_type))
+ {
+ /* if non-service change indication/notification, forward to application */
+ if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, ¬ify, handle))
+ {
+ /* if app registered for the notification */
+ if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, ¬ify))
+ {
+ /* connection not open yet */
+ if (p_clcb == NULL)
+ {
+ if ((p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda)) != NULL)
+ {
+ p_clcb->bta_conn_id = conn_id;
+
+ /* send connection event */
+ bta_gattc_send_open_cback(p_clrcb,
+ BTA_GATT_OK,
+ remote_bda,
+ conn_id);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("No resources");
+ }
+ }
+
+ if (p_clcb != NULL)
+ bta_gattc_proc_other_indication(p_clcb, op, p_data, ¬ify);
+ }
+ /* no one intersted and need ack? */
+ else if (op == GATTC_OPTYPE_INDICATION)
+ {
+ APPL_TRACE_DEBUG0("no one interested, ack now");
+ GATTC_SendHandleValueConfirm(conn_id, handle);
+ }
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Indi/Notif for Unknown handle[0x%04x], can not find in local cache.", handle);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_cmpl_cback
+**
+** Description client operation complete callback register with BTE GATT.
+**
+** Returns None.
+**
+*******************************************************************************/
+static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+ tGATT_CL_COMPLETE *p_data)
+{
+ tBTA_GATTC_CLCB *p_clcb ;
+ tBTA_GATTC_OP_CMPL *p_buf;
+ UINT16 len = sizeof(tBTA_GATTC_OP_CMPL) + sizeof(tGATT_CL_COMPLETE);
+
+ APPL_TRACE_DEBUG3("bta_gattc_cmpl_cback: conn_id = %d op = %d status = %d",
+ conn_id, op, status);
+
+ /* notification and indication processed right away */
+ if (op == GATTC_OPTYPE_NOTIFICATION || op == GATTC_OPTYPE_INDICATION)
+ {
+ bta_gattc_process_indicate(conn_id, op, p_data);
+ return;
+ }
+ /* for all other operation, not expected if w/o connection */
+ else if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) == NULL)
+ {
+ APPL_TRACE_ERROR1("bta_gattc_cmpl_cback unknown conn_id = %d, ignore data", conn_id);
+ return;
+ }
+
+
+ if ((p_buf = (tBTA_GATTC_OP_CMPL *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_buf, 0, len);
+ p_buf->hdr.event = BTA_GATTC_OP_CMPL_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->status = status;
+ p_buf->op_code = op;
+
+ if (p_data != NULL)
+ {
+ p_buf->p_cmpl = (tGATT_CL_COMPLETE *)(p_buf + 1);
+ memcpy(p_buf->p_cmpl, p_data, sizeof(tGATT_CL_COMPLETE));
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+
+ return;
+}
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c
new file mode 100644
index 0000000..1cace7d
--- /dev/null
+++ b/bta/gatt/bta_gattc_api.c
@@ -0,0 +1,934 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation of the API for GATT module of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gattc_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_gatt_reg =
+{
+ bta_gattc_hdl_event,
+ NULL /* need a disable functino to be called when BT is disabled */
+};
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_AppRegister
+**
+** Description This function is called to register application callbacks
+** with BTA GATTC module.
+**
+** Parameters p_app_uuid - applicaiton UUID
+** p_client_cb - pointer to the application callback function.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb)
+{
+ tBTA_GATTC_API_REG *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_GATTC, &bta_gatt_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_GATTC_API_REG *) GKI_getbuf(sizeof(tBTA_GATTC_API_REG))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTC_API_REG_EVT;
+ if (p_app_uuid != NULL)
+ memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
+ p_buf->p_cback = p_client_cb;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_AppDeregister
+**
+** Description This function is called to deregister an application
+** from BTA GATTC module.
+**
+** Parameters client_if - client interface identifier.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if)
+{
+ tBTA_GATTC_API_DEREG *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_DEREG *) GKI_getbuf(sizeof(tBTA_GATTC_API_DEREG))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTC_API_DEREG_EVT;
+ p_buf->client_if = client_if;
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_Open
+**
+** Description Open a direct connection or add a background auto connection
+** bd address
+**
+** Parameters client_if: server interface.
+** remote_bda: remote device BD address.
+** is_direct: direct connection or background auto connection
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+ tBTA_GATTC_API_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTC_API_OPEN_EVT;
+
+ p_buf->client_if = client_if;
+ p_buf->is_direct = is_direct;
+ memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_CancelOpen
+**
+** Description Cancel a direct open connection or remove a background auto connection
+** bd address
+**
+** Parameters client_if: server interface.
+** remote_bda: remote device BD address.
+** is_direct: direct connection or background auto connection
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+ tBTA_GATTC_API_CANCEL_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_CANCEL_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_CANCEL_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTC_API_CANCEL_OPEN_EVT;
+
+ p_buf->client_if = client_if;
+ p_buf->is_direct = is_direct;
+ memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_Close
+**
+** Description Close a connection to a GATT server.
+**
+** Parameters conn_id: connectino ID to be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTC_Close(UINT16 conn_id)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_GATTC_API_CLOSE_EVT;
+
+ p_buf->layer_specific = conn_id;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_ServiceSearchRequest
+**
+** Description This function is called to request a GATT service discovery
+** on a GATT server. This function report service search result
+** by a callback event, and followed by a service search complete
+** event.
+**
+** Parameters conn_id: connection ID.
+** p_srvc_uuid: a UUID of the service application is interested in.
+** If Null, discover for all services.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_ServiceSearchRequest (UINT16 conn_id, tBT_UUID *p_srvc_uuid)
+{
+ tBTA_GATTC_API_SEARCH *p_buf;
+ UINT16 len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(tBT_UUID);
+
+ if ((p_buf = (tBTA_GATTC_API_SEARCH *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_buf, 0, len);
+
+ p_buf->hdr.event = BTA_GATTC_API_SEARCH_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+
+ if (p_srvc_uuid)
+ {
+ memcpy(&p_buf->srvc_uuid, p_srvc_uuid, sizeof(tBT_UUID));
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetFirstChar
+**
+** Description This function is called to find the first charatceristic of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_srvc_id: the service ID of which the characteristic is belonged to.
+** p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+** characteristic.
+** p_char_result: output parameter which will store the GATT
+** characteristic ID.
+** p_property: output parameter to carry the characteristic property.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_GetFirstChar (UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
+ tBT_UUID *p_char_uuid_cond,
+ tBTA_GATTC_CHAR_ID *p_char_result,
+ tBTA_GATT_CHAR_PROP *p_property)
+{
+ tBTA_GATT_STATUS status;
+
+ if (!p_srvc_id || !p_char_result)
+ return BTA_GATT_ILLEGAL_PARAMETER;
+
+ if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR, p_srvc_id, NULL,
+ p_char_uuid_cond, &p_char_result->char_id, p_property))
+ == BTA_GATT_OK)
+ {
+ memcpy(&p_char_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ }
+
+ return status;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetNextChar
+**
+** Description This function is called to find the next charatceristic of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_start_char_id: start the characteristic search from the next record
+** after the one identified by char_id.
+** p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+** characteristic.
+** p_char_result: output parameter which will store the GATT
+** characteristic ID.
+** p_property: output parameter to carry the characteristic property.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_GetNextChar (UINT16 conn_id,
+ tBTA_GATTC_CHAR_ID *p_start_char_id,
+ tBT_UUID *p_char_uuid_cond,
+ tBTA_GATTC_CHAR_ID *p_char_result,
+ tBTA_GATT_CHAR_PROP *p_property)
+{
+ tBTA_GATT_STATUS status;
+
+ if (!p_start_char_id || !p_char_result)
+ return BTA_GATT_ILLEGAL_PARAMETER;
+
+ if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR,
+ &p_start_char_id->srvc_id,
+ &p_start_char_id->char_id,
+ p_char_uuid_cond,
+ &p_char_result->char_id,
+ p_property))
+ == BTA_GATT_OK)
+ {
+ memcpy(&p_char_result->srvc_id, &p_start_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetFirstCharDescr
+**
+** Description This function is called to find the first charatceristic descriptor of the
+** charatceristic on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_char_id: the characteristic ID of which the descriptor is belonged to.
+** p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
+** characteristic.
+** p_descr_result: output parameter which will store the GATT
+** characteristic descriptor ID.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+ tBT_UUID *p_descr_uuid_cond,
+ tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
+{
+ tBTA_GATT_STATUS status;
+
+ if (!p_char_id || !p_descr_result)
+ return BTA_GATT_ILLEGAL_PARAMETER;
+
+ memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
+
+ if ((status = bta_gattc_query_cache(conn_id,
+ BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+ &p_char_id->srvc_id,
+ &p_char_id->char_id,
+ p_descr_uuid_cond,
+ &p_descr_result->char_id.char_id,
+ NULL))
+ == BTA_GATT_OK)
+ {
+ memcpy(&p_descr_result->descr_type, &p_descr_result->char_id.char_id.uuid, sizeof(tBT_UUID));
+ memcpy(&p_descr_result->char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
+ }
+
+ return status;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetNextCharDescr
+**
+** Description This function is called to find the next charatceristic of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_start_descr_id: start the characteristic search from the next record
+** after the one identified by p_start_descr_id.
+** p_descr_uuid_cond: Characteristic descriptor UUID, if NULL find
+** the first available characteristic descriptor.
+** p_descr_result: output parameter which will store the GATT
+** characteristic descriptor ID.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_GetNextCharDescr (UINT16 conn_id,
+ tBTA_GATTC_CHAR_DESCR_ID *p_start_descr_id,
+ tBT_UUID *p_descr_uuid_cond,
+ tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
+{
+ tBTA_GATT_STATUS status;
+
+ if (!p_start_descr_id || !p_descr_result)
+ return BTA_GATT_ILLEGAL_PARAMETER;
+
+ memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
+
+ if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+ &p_start_descr_id->char_id.srvc_id,
+ &p_start_descr_id->char_id.char_id,
+ p_descr_uuid_cond,
+ &p_descr_result->char_id.char_id,
+ (void *)&p_start_descr_id->descr_type))
+ == BTA_GATT_OK)
+ {
+ memcpy(&p_descr_result->descr_type, &p_descr_result->char_id.char_id.uuid, sizeof(tBT_UUID));
+ memcpy(&p_descr_result->char_id, p_start_descr_id, sizeof(tBTA_GATTC_CHAR_ID));
+ }
+
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetFirstIncludedService
+**
+** Description This function is called to find the first included service of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_srvc_id: the service ID of which the characteristic is belonged to.
+** p_uuid_cond: Characteristic UUID, if NULL find the first available
+** characteristic.
+** p_result: output parameter which will store the GATT ID
+** of the included service found.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_GetFirstIncludedService(UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
+ tBT_UUID *p_uuid_cond, tBTA_GATTC_INCL_SVC_ID *p_result)
+{
+ tBTA_GATT_STATUS status;
+
+ if (!p_srvc_id || !p_result)
+ return BTA_GATT_ILLEGAL_PARAMETER;
+
+ if ((status = bta_gattc_query_cache(conn_id,
+ BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+ p_srvc_id,
+ NULL,
+ p_uuid_cond,
+ &p_result->incl_svc_id.id,
+ (tBTA_GATT_CHAR_PROP *)&p_result->incl_svc_id.is_primary))
+ == BTA_GATT_OK)
+ {
+ memcpy(&p_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ }
+
+ return status;
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetNextIncludedService
+**
+** Description This function is called to find the next included service of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_start_id: start the search from the next record
+** after the one identified by p_start_id.
+** p_uuid_cond: Included service UUID, if NULL find the first available
+** included service.
+** p_result: output parameter which will store the GATT ID
+** of the included service found.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
+ tBTA_GATTC_INCL_SVC_ID *p_start_id,
+ tBT_UUID *p_uuid_cond,
+ tBTA_GATTC_INCL_SVC_ID *p_result)
+{
+ tBTA_GATT_STATUS status;
+
+ if (!p_start_id || !p_result)
+ return BTA_GATT_ILLEGAL_PARAMETER;
+
+ if ((status = bta_gattc_query_cache(conn_id,
+ BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+ &p_start_id->srvc_id,
+ &p_start_id->incl_svc_id.id,
+ p_uuid_cond,
+ &p_result->incl_svc_id.id,
+ (tBTA_GATT_CHAR_PROP *)&p_result->incl_svc_id.is_primary))
+ == BTA_GATT_OK)
+ {
+ memcpy(&p_result->srvc_id, &p_start_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_ReadCharacteristic
+**
+** Description This function is called to read a service's characteristics of
+** the given characteritisc ID.
+**
+** Parameters conn_id - connectino ID.
+** p_char_id - characteritic ID to read.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+ tBTA_GATT_AUTH_REQ auth_req)
+{
+ tBTA_GATTC_API_READ *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_READ *) GKI_getbuf(sizeof(tBTA_GATTC_API_READ))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_GATTC_API_READ));
+
+ p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->auth_req = auth_req;
+
+ memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_ReadCharDescr
+**
+** Description This function is called to read a characteristics descriptor.
+**
+** Parameters conn_id - connection ID.
+** p_char_descr_id - characteritic descriptor ID to read.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
+ tBTA_GATTC_CHAR_DESCR_ID *p_descr_id,
+ tBTA_GATT_AUTH_REQ auth_req)
+{
+ tBTA_GATTC_API_READ *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_READ *) GKI_getbuf(sizeof(tBTA_GATTC_API_READ))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_GATTC_API_READ));
+
+ p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->auth_req = auth_req;
+
+ memcpy(&p_buf->srvc_id, &p_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ memcpy(&p_buf->char_id, &p_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
+ memcpy(&p_buf->descr_type, &p_descr_id->descr_type, sizeof(tBT_UUID));
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_ReadMultiple
+**
+** Description This function is called to read multiple characteristic or
+** characteristic descriptors.
+**
+** Parameters conn_id - connectino ID.
+** p_read_multi - pointer to the read multiple parameter.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
+ tBTA_GATT_AUTH_REQ auth_req)
+{
+ tBTA_GATTC_API_READ_MULTI *p_buf;
+ tBTA_GATTC_ATTR_ID *p_value;
+ UINT16 len = (UINT16)(sizeof(tBTA_GATTC_API_READ_MULTI) +
+ p_read_multi->num_attr * sizeof(tBTA_GATTC_ATTR_ID));
+ UINT8 i;
+
+ if ((p_buf = (tBTA_GATTC_API_READ_MULTI *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_buf, 0, len);
+
+ p_buf->hdr.event = BTA_GATTC_API_READ_MULTI_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->auth_req = auth_req;
+
+ p_buf->num_attr = p_read_multi->num_attr;
+
+ if (p_buf->num_attr > 0)
+ {
+ p_buf->p_id_list = p_value = (tBTA_GATTC_ATTR_ID *)(p_buf + 1);
+
+ for (i = 0; i < p_buf->num_attr; i ++, p_value ++)
+ {
+ memcpy(p_value, &p_read_multi->id_list[i], sizeof(tBTA_GATTC_ATTR_ID));
+ }
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_WriteCharValue
+**
+** Description This function is called to write characteristic value.
+**
+** Parameters conn_id - connection ID.
+** p_char_id - characteristic ID to write.
+** write_type - type of write.
+** len: length of the data to be written.
+** p_value - the value to be written.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_WriteCharValue ( UINT16 conn_id,
+ tBTA_GATTC_CHAR_ID *p_char_id,
+ tBTA_GATTC_WRITE_TYPE write_type,
+ UINT16 len,
+ UINT8 *p_value,
+ tBTA_GATT_AUTH_REQ auth_req)
+{
+ tBTA_GATTC_API_WRITE *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_WRITE) + len))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_GATTC_API_WRITE) + len);
+
+ p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->auth_req = auth_req;
+
+ memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+ p_buf->write_type = write_type;
+ p_buf->len = len;
+
+ if (p_value && len > 0)
+ {
+ p_buf->p_value = (UINT8 *)(p_buf + 1);
+ memcpy(p_buf->p_value, p_value, len);
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_WriteCharDescr
+**
+** Description This function is called to write characteristic descriptor value.
+**
+** Parameters conn_id - connection ID
+** p_char_descr_id - characteristic descriptor ID to write.
+** write_type - write type.
+** p_value - the value to be written.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
+ tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+ tBTA_GATTC_WRITE_TYPE write_type,
+ tBTA_GATT_UNFMT *p_data,
+ tBTA_GATT_AUTH_REQ auth_req)
+{
+ tBTA_GATTC_API_WRITE *p_buf;
+ UINT16 len = sizeof(tBTA_GATTC_API_WRITE) + p_data->len;
+
+ if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_buf, 0, len);
+
+ p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->auth_req = auth_req;
+
+ memcpy(&p_buf->srvc_id, &p_char_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ memcpy(&p_buf->char_id, &p_char_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
+ memcpy(&p_buf->descr_type, &p_char_descr_id->descr_type, sizeof(tBT_UUID));
+ p_buf->write_type = write_type;
+
+ if (p_data && p_data->len != 0)
+ {
+ p_buf->p_value = (UINT8 *)(p_buf + 1);
+ p_buf->len = p_data->len;
+ /* pack the descr data */
+ memcpy(p_buf->p_value, p_data->p_value, p_data->len);
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_PrepareWrite
+**
+** Description This function is called to prepare write a characteristic value.
+**
+** Parameters conn_id - connection ID.
+** p_char_id - GATT characteritic ID of the service.
+** offset - offset of the write value.
+** len: length of the data to be written.
+** p_value - the value to be written.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_PrepareWrite (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+ UINT16 offset, UINT16 len, UINT8 *p_value,
+ tBTA_GATT_AUTH_REQ auth_req)
+{
+ tBTA_GATTC_API_WRITE *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_WRITE) + len))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_GATTC_API_WRITE) + len);
+
+ p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->auth_req = auth_req;
+
+ memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+ p_buf->write_type = BTA_GATTC_WRITE_PREPARE;
+ p_buf->offset = offset;
+ p_buf->len = len;
+
+ if (p_value && len > 0)
+ {
+ p_buf->p_value = (UINT8 *)(p_buf + 1);
+ memcpy(p_buf->p_value, p_value, len);
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_ExecuteWrite
+**
+** Description This function is called to execute write a prepare write sequence.
+**
+** Parameters conn_id - connection ID.
+** is_execute - execute or cancel.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute)
+{
+ tBTA_GATTC_API_EXEC *p_buf;
+
+ if ((p_buf = (tBTA_GATTC_API_EXEC *) GKI_getbuf((UINT16)sizeof(tBTA_GATTC_API_EXEC))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_GATTC_API_EXEC));
+
+ p_buf->hdr.event = BTA_GATTC_API_EXEC_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+
+ p_buf->is_execute = is_execute;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTC_SendIndConfirm
+**
+** Description This function is called to send handle value confirmation.
+**
+** Parameters conn_id - connection ID.
+** p_char_id - characteristic ID to confirm.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id)
+{
+ tBTA_GATTC_API_CONFIRM *p_buf;
+
+ APPL_TRACE_API3("BTA_GATTC_SendIndConfirm conn_id=%d service uuid1=0x%x char uuid=0x%x",
+ conn_id, p_char_id->srvc_id.id.uuid.uu.uuid16, p_char_id->char_id.uuid.uu.uuid16); //toto
+
+ if ((p_buf = (tBTA_GATTC_API_CONFIRM *) GKI_getbuf(sizeof(tBTA_GATTC_API_CONFIRM))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_GATTC_API_CONFIRM));
+
+ p_buf->hdr.event = BTA_GATTC_API_CONFIRM_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+
+ memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+ memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_RegisterForNotifications
+**
+** Description This function is called to register for notification of a service.
+**
+** Parameters client_if - client interface.
+** bda - target GATT server.
+** p_char_id - pointer to GATT characteristic ID.
+**
+** Returns OK if registration succeed, otherwise failed.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
+ BD_ADDR bda,
+ tBTA_GATTC_CHAR_ID *p_char_id)
+{
+ tBTA_GATTC_RCB *p_clreg;
+ tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
+ UINT8 i;
+
+ if (!p_char_id)
+ {
+ APPL_TRACE_ERROR0("deregistration failed, unknow char id");
+ return status;
+ }
+
+ /* lock other GKI task */
+ GKI_sched_lock();
+
+ if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
+ {
+ for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+ {
+ if (!p_clreg->notif_reg[i].in_use)
+ {
+ memset(&p_clreg->notif_reg, 0, sizeof(tBTA_GATTC_NOTIF_REG));
+
+ p_clreg->notif_reg[i].in_use = TRUE;
+ memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);
+ memcpy(&p_clreg->notif_reg[i].char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
+
+ status = BTA_GATT_OK;
+ break;
+ }
+ }
+ if (i == BTA_GATTC_NOTIF_REG_MAX)
+ {
+ status = BTA_GATT_NO_RESOURCES;
+ APPL_TRACE_ERROR0("Max Notification Reached, registration failed.");
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Client_if: %d Not Registered", client_if);
+ }
+
+ GKI_sched_unlock();
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_DeregisterForNotifications
+**
+** Description This function is called to de-register for notification of a service.
+**
+** Parameters client_if - client interface.
+** bda - target GATT server.
+** p_char_id - pointer to GATT characteristic ID.
+**
+** Returns OK if deregistration succeed, otherwise failed.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
+ BD_ADDR bda,
+ tBTA_GATTC_CHAR_ID *p_char_id)
+{
+ tBTA_GATTC_RCB *p_clreg;
+ tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
+ UINT8 i;
+
+ if (!p_char_id)
+ {
+ APPL_TRACE_ERROR0("deregistration failed, unknow char id");
+ return status;
+ }
+
+ /* lock other GKI task */
+ GKI_sched_lock();
+
+ if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
+ {
+ for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+ {
+ if (p_clreg->notif_reg[i].in_use &&
+ !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
+ !memcmp(&p_clreg->notif_reg[i].char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID)))
+ {
+ APPL_TRACE_DEBUG0("Deregistered.");
+
+ memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+ status = BTA_GATT_OK;
+ break;
+ }
+ }
+ if (i == BTA_GATTC_NOTIF_REG_MAX)
+ {
+ status = BTA_GATT_ERROR;
+
+ APPL_TRACE_ERROR0("registration not found");
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Client_if: %d Not Registered", client_if);
+ }
+
+ GKI_sched_unlock();
+
+ return status;
+}
+
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c
new file mode 100644
index 0000000..3774df4
--- /dev/null
+++ b/bta/gatt/bta_gattc_cache.c
@@ -0,0 +1,1597 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the GATT client discovery procedures and cache
+ * related functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "sdp_api.h"
+#include "sdpdefs.h"
+#include "bta_gattc_int.h"
+#include "btm_api.h"
+
+static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
+static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
+
+#define BTA_GATT_SDP_DB_SIZE 750
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+static char *bta_gattc_attr_type[] =
+{
+ "I", /* Included Service */
+ "C", /* Characteristic */
+ "D" /* Characteristic Descriptor */
+};
+/* utility functions */
+
+/*******************************************************************************
+**
+** Function bta_gattc_display_cache_server
+**
+** Description debug function to display the server cache.
+**
+** Returns none.
+**
+*******************************************************************************/
+static void bta_gattc_display_cache_server(tBTA_GATTC_CACHE *p_cache)
+{
+ UINT8 i = 0, j;
+ tBTA_GATTC_CACHE *p_cur_srvc = p_cache;
+ tBTA_GATTC_CACHE_ATTR *p_attr;
+
+ APPL_TRACE_ERROR0("<================Start Server Cache =============>");
+
+ while (p_cur_srvc)
+ {
+ APPL_TRACE_ERROR6("Service[%d]: handle[%d ~ %d] %s[0x%04x] inst[%d]",
+ i, p_cur_srvc->s_handle, p_cur_srvc->e_handle,
+ ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
+ p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
+ p_cur_srvc->service_uuid.id.inst_id);
+ i ++;
+
+ p_attr = p_cur_srvc->p_attr;
+
+ for (j = 0; p_attr; j ++ )
+ {
+ APPL_TRACE_ERROR6("\t Attr[0x%04x] handle[%d] uuid[0x%04x] inst[%d] type[%s] prop[0x%1x]",
+ j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id,
+ bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
+
+ p_attr = p_attr->p_next;
+ }
+ p_cur_srvc = p_cur_srvc->p_next;
+ }
+
+ APPL_TRACE_ERROR0("<================End Server Cache =============>");
+ APPL_TRACE_ERROR0(" ");
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_display_explore_record
+**
+** Description debug function to display the exploration list
+**
+** Returns none.
+**
+*******************************************************************************/
+static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec)
+{
+ UINT8 i;
+ tBTA_GATTC_ATTR_REC *pp = p_rec;
+
+ APPL_TRACE_ERROR0("<================Start Explore Queue =============>");
+ for (i = 0; i < num_rec; i ++, pp ++)
+ {
+ APPL_TRACE_ERROR5("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
+ i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
+ }
+ APPL_TRACE_ERROR0("<================ End Explore Queue =============>");
+ APPL_TRACE_ERROR0(" ");
+
+}
+#endif /* BTA_GATT_DEBUG == TRUE */
+
+
+/*******************************************************************************
+**
+** Function bta_gattc_alloc_cache_buf
+**
+** Description Allocate a GKI buffer for database cache.
+**
+** Returns status
+**
+*******************************************************************************/
+BT_HDR *bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV *p_srvc_cb)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *)GKI_getpoolbuf(GATT_DB_POOL_ID)) == NULL)
+ {
+ APPL_TRACE_DEBUG0("No resources: GKI buffer allocation failed.");
+ utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
+ p_srvc_cb->free_byte = 0;
+ }
+ else
+ {
+ memset(p_buf, 0, GKI_get_buf_size(p_buf));
+ p_srvc_cb->p_free = (UINT8 *) p_buf;
+ p_srvc_cb->free_byte = GKI_get_buf_size(p_buf);
+
+ /* link into buffer queue */
+ GKI_enqueue(&p_srvc_cb->cache_buffer, p_buf);
+ }
+#if BTA_GATT_DEBUG== TRUE
+ APPL_TRACE_DEBUG1("allocating new buffer: free byte = %d", p_srvc_cb->free_byte);
+#endif
+ return p_buf;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_init_cache
+**
+** Description Initialize the database cache and discovery related resources.
+**
+** Returns status
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
+{
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+ while (p_srvc_cb->cache_buffer.p_first)
+ GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+ utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
+
+ if ((p_srvc_cb->p_srvc_list = (tBTA_GATTC_ATTR_REC*)GKI_getbuf(BTA_GATTC_ATTR_LIST_SIZE)) == NULL)
+ {
+ APPL_TRACE_DEBUG0("No resources: GKI buffer allocation failed.");
+ status = GATT_NO_RESOURCES;
+ }
+ else
+ {
+ p_srvc_cb->total_srvc = 0;
+ p_srvc_cb->cur_srvc_idx =
+ p_srvc_cb->cur_char_idx =
+ p_srvc_cb->next_avail_idx = 0;
+
+ if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+ {
+ status = GATT_NO_RESOURCES;
+ }
+ else
+ {
+ p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
+ }
+ }
+
+ return status;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_get_srvc_inst_id
+**
+** Description get service instance number
+**
+** Returns instance ID of the service.
+**
+*******************************************************************************/
+static UINT8 bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID uuid)
+{
+ UINT8 i = 0, inst = 0;
+ tBTA_GATTC_ATTR_REC *p_srvc_rec;
+
+ for (i = 0; i < p_srvc_cb->total_srvc; i ++)
+ /*
+ for (; i < p_srvc_cb->cur_srvc_idx; i ++)*/
+ {
+ p_srvc_rec = p_srvc_cb->p_srvc_list + i;
+
+ if (bta_gattc_uuid_compare(p_srvc_rec->uuid, uuid, TRUE))
+ inst ++;
+ }
+ return inst ;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_get_char_inst_id
+**
+** Description get characteristic instance number
+**
+** Returns characteristic instance ID.
+**
+*******************************************************************************/
+static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID uuid)
+{
+ UINT8 inst = 0;
+ tBTA_GATTC_CACHE_ATTR *p_attr;
+ tBT_UUID attr_uuid;
+
+ p_attr = p_service_cache->p_attr;
+
+ while (p_attr)
+ {
+ bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
+
+ if (bta_gattc_uuid_compare(attr_uuid, uuid, TRUE))
+ inst ++;
+
+ p_attr = p_attr->p_next;
+ }
+ return inst ;
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_add_srvc_to_cache
+**
+** Description Add a service into database cache.
+**
+** Returns status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
+ UINT16 s_handle, UINT16 e_handle,
+ tBT_UUID *p_uuid,
+ BOOLEAN is_primary, UINT8 srvc_inst)
+{
+ tBTA_GATTC_CACHE *p_new_srvc = NULL;
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("Add a service into Service");
+ APPL_TRACE_DEBUG2("free byte = %d, req %d bytes.", p_srvc_cb->free_byte, sizeof(tBTA_GATTC_CACHE))
+#endif
+
+ if (p_srvc_cb->free_byte < sizeof(tBTA_GATTC_CACHE))
+ {
+ if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+ return GATT_NO_RESOURCES;
+ }
+
+ p_new_srvc = (tBTA_GATTC_CACHE *)p_srvc_cb->p_free;
+ /* update service information */
+ p_new_srvc->s_handle = s_handle;
+ p_new_srvc->e_handle = e_handle;
+ p_new_srvc->service_uuid.is_primary = is_primary;
+ memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
+ p_new_srvc->service_uuid.id.inst_id = srvc_inst;
+ p_new_srvc->p_next = NULL;
+
+ if (p_srvc_cb->p_cur_srvc != NULL)
+ p_srvc_cb->p_cur_srvc->p_next = p_new_srvc;
+ p_srvc_cb->p_cur_srvc = p_new_srvc;
+
+ /* first service */
+ if (p_srvc_cb->p_srvc_cache == NULL)
+ p_srvc_cb->p_srvc_cache = p_new_srvc;
+
+ /* update buffer managament info */
+ p_srvc_cb->p_free += sizeof(tBTA_GATTC_CACHE);
+ p_srvc_cb->free_byte -= sizeof(tBTA_GATTC_CACHE);
+
+
+#if 0
+//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+#endif
+ return status;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_add_attr_to_cache
+**
+** Description Add an attribute into database cache buffer.
+**
+** Returns status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
+ UINT16 handle,
+ tBT_UUID *p_uuid,
+ UINT8 property,
+ tBTA_GATTC_ATTR_TYPE type)
+{
+ tBTA_GATTC_CACHE_ATTR *p_attr;
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+ UINT16 len = sizeof(tBTA_GATTC_CACHE_ATTR) + p_uuid->len;
+ UINT8 *pp;
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG1("bta_gattc_add_attr_to_cache: Add a [%s] into Service", bta_gattc_attr_type[type]);
+ APPL_TRACE_DEBUG4("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
+ APPL_TRACE_DEBUG2("free byte = %d, req %d bytes.", p_srvc_cb->free_byte, len);
+#endif
+
+ if (p_srvc_cb->free_byte < len)
+ {
+ if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+ return GATT_NO_RESOURCES;
+ }
+
+ p_attr = (tBTA_GATTC_CACHE_ATTR *)p_srvc_cb->p_free;
+
+ p_attr->attr_handle = handle;
+ p_attr->attr_type = type;
+ p_attr->property = property;
+ p_attr->uuid_len = p_uuid->len;
+ p_attr->p_uuid = (tBTA_GATTC_UUID *)(p_attr + 1);
+ p_attr->p_next = NULL;
+
+ pp = (UINT8 *)p_attr->p_uuid;
+
+ if (p_uuid->len == LEN_UUID_16)
+ {
+ UINT16_TO_STREAM(pp, p_uuid->uu.uuid16);
+ }
+ else if (p_uuid->len == LEN_UUID_128)
+ {
+ memcpy(pp, p_uuid->uu.uuid128, LEN_UUID_128);
+ }
+
+ if (type == BTA_GATTC_ATTR_TYPE_CHAR)
+ p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, *p_uuid);
+ /* else: char descriptor, no instance ID needed */
+ else /* TODO: --->> temp treat included service same as char descriptor */
+ p_attr->inst_id = 0;
+
+ /* update service information */
+ p_srvc_cb->p_free += len;
+ p_srvc_cb->free_byte -= len;
+
+ /* first attribute within the service, update the attribute pointer */
+ if (p_srvc_cb->p_cur_srvc->p_attr == NULL)
+ {
+ p_srvc_cb->p_cur_srvc->p_attr = p_attr;
+ }
+ if (p_srvc_cb->p_cur_srvc->p_last_attr != NULL)
+ p_srvc_cb->p_cur_srvc->p_last_attr->p_next = p_attr;
+
+ p_srvc_cb->p_cur_srvc->p_last_attr = p_attr;
+
+#if 0
+//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+#endif
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_get_disc_range
+**
+** Description get discovery stating and ending handle range.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc)
+{
+ tBTA_GATTC_ATTR_REC *p_rec = NULL;
+
+ if (is_srvc)
+ {
+ p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
+ *p_s_hdl = p_rec->s_handle;
+ }
+ else
+ {
+ p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
+ *p_s_hdl = p_rec->s_handle + 1;
+ }
+
+ *p_e_hdl = p_rec->e_handle;
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG2("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle);
+#endif
+ return;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_discover_pri_service
+**
+** Description Start primary service discovery
+**
+** Returns status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type)
+{
+#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+ tBT_DEVICE_TYPE dev_type;
+ tBLE_ADDR_TYPE addr_type;
+
+ BTM_ReadDevInfo(p_server_cb->server_bda, &dev_type, &addr_type);
+ if (dev_type == BT_DEVICE_TYPE_BLE)
+ return bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
+ else
+ return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
+#endif
+ return BTA_GATT_ERROR;
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_discover_procedure
+**
+** Description Start a particular type of discovery procedure on server.
+**
+** Returns status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type)
+{
+ tGATT_DISC_PARAM param;
+ BOOLEAN is_service = TRUE;
+
+ memset(¶m, 0, sizeof(tGATT_DISC_PARAM));
+
+ if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID)
+ {
+ param.s_handle = 1;
+ param.e_handle = 0xFFFF;
+ }
+ else
+ {
+ if (disc_type == GATT_DISC_CHAR_DSCPT)
+ is_service = FALSE;
+
+ bta_gattc_get_disc_range(p_server_cb, ¶m.s_handle, ¶m.e_handle, is_service);
+
+ if (param.s_handle > param.e_handle)
+ {
+ APPL_TRACE_ERROR2("discover range invalid: [0x%04x ~ 0x%04x]", param.s_handle, param.e_handle);
+
+ return GATT_ERROR;
+ }
+ }
+ return GATTC_Discover (conn_id, disc_type, ¶m);
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_start_disc_include_srvc
+**
+** Description Start discovery for included service
+**
+** Returns status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+ APPL_TRACE_DEBUG0("starting discovery included service");
+
+ return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_start_disc_char
+**
+** Description Start discovery for characteristic
+**
+** Returns status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+ p_srvc_cb->total_char = 0;
+
+ APPL_TRACE_DEBUG0("starting discover characteristics");
+
+ return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_start_disc_char_dscp
+**
+** Description Start discovery for characteristic descriptor
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+ APPL_TRACE_DEBUG0("starting discover characteristics descriptor");
+
+ if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0)
+ bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_explore_srvc
+**
+** Description process the service discovery complete event
+**
+** Returns status
+**
+*******************************************************************************/
+static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+ tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
+ tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+ APPL_TRACE_DEBUG1("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx);
+
+ p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
+
+ if (p_clcb == NULL)
+ {
+ APPL_TRACE_ERROR0("unknown connection ID");
+ return;
+ }
+ /* start expore a service if there is service not been explored */
+ if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc)
+ {
+ /* add the first service into cache */
+ if (bta_gattc_add_srvc_to_cache (p_srvc_cb,
+ p_rec->s_handle,
+ p_rec->e_handle,
+ &p_rec->uuid,
+ p_rec->is_primary,
+ p_rec->srvc_inst_id) == 0)
+ {
+ /* start discovering included services */
+ bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
+ return;
+ }
+ }
+ /* no service found at all, the end of server discovery*/
+ APPL_TRACE_ERROR0("No More Service found");
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+#endif
+ /* save cache to NV */
+ p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
+ bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
+ conn_id, TRUE);
+ //bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_incl_srvc_disc_cmpl
+**
+** Description process the relationship discovery complete event
+**
+** Returns status
+**
+*******************************************************************************/
+static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+ p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
+
+ /* start discoverying characteristic */
+ bta_gattc_start_disc_char(conn_id, p_srvc_cb);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_char_disc_cmpl
+**
+** Description process the characteristic discovery complete event
+**
+** Returns status
+**
+*******************************************************************************/
+static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+ tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
+
+ APPL_TRACE_DEBUG1("Total %d Char found ", p_srvc_cb->total_char);
+
+ /* if there are characteristic needs to be explored */
+ if (p_srvc_cb->total_char > 0)
+ {
+ /* add the first characteristic into cache */
+ bta_gattc_add_attr_to_cache (p_srvc_cb,
+ p_rec->s_handle,
+ &p_rec->uuid,
+ p_rec->property,
+ BTA_GATTC_ATTR_TYPE_CHAR);
+
+ /* start discoverying characteristic descriptor , if failed, disc for next char*/
+ bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
+ }
+ else /* otherwise start with next service */
+ {
+ p_srvc_cb->cur_srvc_idx ++;
+
+ bta_gattc_explore_srvc (conn_id, p_srvc_cb);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_char_dscpt_disc_cmpl
+**
+** Description process the char descriptor discovery complete event
+**
+** Returns status
+**
+*******************************************************************************/
+static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+ tBTA_GATTC_ATTR_REC *p_rec = NULL;
+
+ if (-- p_srvc_cb->total_char > 0)
+ {
+ p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
+ /* add the next characteristic into cache */
+ bta_gattc_add_attr_to_cache (p_srvc_cb,
+ p_rec->s_handle,
+ &p_rec->uuid,
+ p_rec->property,
+ BTA_GATTC_ATTR_TYPE_CHAR);
+
+ /* start discoverying next characteristic for char descriptor */
+ bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
+ }
+ else
+ /* all characteristic has been explored, start with next service if any */
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_ERROR0("all char has been explored");
+#endif
+ p_srvc_cb->cur_srvc_idx ++;
+ bta_gattc_explore_srvc (conn_id, p_srvc_cb);
+ }
+
+}
+static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle,
+ UINT16 e_handle, tBT_UUID uuid)
+{
+ tBTA_GATTC_ATTR_REC *p_rec = NULL;
+ UINT8 i;
+ BOOLEAN exist_srvc = FALSE;
+
+ if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle))
+ {
+ APPL_TRACE_ERROR2("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle);
+ exist_srvc = TRUE;
+ }
+ else
+ {
+ for (i = 0; i < p_srvc_cb->next_avail_idx; i ++)
+ {
+ p_rec = p_srvc_cb->p_srvc_list + i;
+
+ /* a new service should not have any overlap with other service handle range */
+ if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle)
+ {
+ exist_srvc = TRUE;
+ break;
+ }
+ }
+ }
+ return exist_srvc;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_add_srvc_to_list
+**
+** Description Add a service into explore pending list
+**
+** Returns status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
+ UINT16 s_handle, UINT16 e_handle,
+ tBT_UUID uuid, BOOLEAN is_primary)
+{
+ tBTA_GATTC_ATTR_REC *p_rec = NULL;
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+ if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
+ {
+ p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
+
+ p_srvc_cb->total_srvc ++;
+
+ APPL_TRACE_DEBUG2("bta_gattc_add_srvc_to_list handle = %d, service type = 0x%04x",
+ s_handle, uuid.uu.uuid16);
+
+ p_rec->s_handle = s_handle;
+ p_rec->e_handle = e_handle;
+ p_rec->is_primary = is_primary;
+ p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid);
+ memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
+
+ p_srvc_cb->next_avail_idx ++;
+
+ }
+ else
+ { /* allocate bigger buffer ?? */
+ status = GATT_DB_FULL;
+
+ APPL_TRACE_ERROR0("char not added, no resources");
+ }
+ return status;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_add_char_to_list
+**
+** Description Add a characteristic into explore pending list
+**
+** Returns status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
+ UINT16 decl_handle, UINT16 value_handle,
+ tBT_UUID uuid, UINT8 property)
+{
+ tBTA_GATTC_ATTR_REC *p_rec = NULL;
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+ if (p_srvc_cb->p_srvc_list == NULL)
+ {
+ APPL_TRACE_ERROR0("No service available, unexpected char discovery result");
+ status = BTA_GATT_INTERNAL_ERROR;
+ }
+ else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
+ {
+
+ p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
+
+ p_srvc_cb->total_char ++;
+
+ p_rec->s_handle = value_handle;
+ p_rec->property = property;
+ p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
+ memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
+
+ /* update the endind handle of pervious characteristic if available */
+ if (p_srvc_cb->total_char > 1)
+ {
+ p_rec -= 1;
+ p_rec->e_handle = decl_handle - 1;
+ }
+ p_srvc_cb->next_avail_idx ++;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("char not added, no resources");
+ /* allocate bigger buffer ?? */
+ status = BTA_GATT_DB_FULL;
+ }
+ return status;
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_sdp_callback
+**
+** Description Process the discovery result from sdp
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_sdp_callback (UINT16 sdp_status)
+{
+ tSDP_DISC_REC *p_sdp_rec = NULL;
+ tBT_UUID service_uuid;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT16 start_handle = 0, end_handle = 0;
+ tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_scb_by_cid(bta_gattc_cb.sdp_conn_id);
+
+ if(((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL)
+ {
+ do
+ {
+ /* find a service record, report it */
+ p_sdp_rec = SDP_FindServiceInDb(bta_gattc_cb.p_sdp_db,
+ 0, p_sdp_rec);
+ if (p_sdp_rec)
+ {
+ if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
+ {
+
+ if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe))
+ {
+ start_handle = (UINT16) pe.params[0];
+ end_handle = (UINT16) pe.params[1];
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_EVENT3("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
+ service_uuid.uu.uuid16, start_handle, end_handle);
+#endif
+
+ if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle) &&
+ p_srvc_cb != NULL)
+ {
+ /* discover services result, add services into a service list */
+ bta_gattc_add_srvc_to_list(p_srvc_cb,
+ start_handle,
+ end_handle,
+ service_uuid,
+ TRUE);
+ }
+ else
+ {
+ APPL_TRACE_ERROR2("invalid start_handle = %d end_handle = %d", start_handle, end_handle);
+ }
+ }
+
+
+ }
+ }
+ } while (p_sdp_rec);
+ }
+
+ if ( p_srvc_cb != NULL)
+ /* start discover primary service */
+ bta_gattc_explore_srvc(bta_gattc_cb.sdp_conn_id, p_srvc_cb);
+ else
+ {
+ APPL_TRACE_ERROR0("GATT service discovery is done on unknown connection");
+ }
+
+ GKI_freebuf(bta_gattc_cb.p_sdp_db);
+ bta_gattc_cb.p_sdp_db = NULL;
+ bta_gattc_cb.sdp_conn_id = 0;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_sdp_service_disc
+**
+** Description Start DSP Service Discovert
+**
+** Returns void
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb)
+{
+ tSDP_UUID uuid;
+ UINT16 num_attrs = 2;
+ UINT16 attr_list[2];
+ tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+
+ memset (&uuid, 0, sizeof(tSDP_UUID));
+
+ uuid.len = LEN_UUID_16;
+ uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
+
+ if((bta_gattc_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_GATT_SDP_DB_SIZE)) != NULL)
+ {
+ attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+ attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+
+ SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, &uuid, num_attrs, attr_list);
+
+ if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda, bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback))
+ {
+ GKI_freebuf(bta_gattc_cb.p_sdp_db);
+ bta_gattc_cb.p_sdp_db = NULL;
+ }
+ else
+ {
+ bta_gattc_cb.sdp_conn_id = conn_id;
+ status = BTA_GATT_OK;
+ }
+ }
+ return status;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_disc_res_cback
+** bta_gattc_disc_cmpl_cback
+**
+** Description callback functions to GATT client stack.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
+{
+ tBTA_GATTC_SERV * p_srvc_cb = NULL;
+ BOOLEAN pri_srvc;
+
+ p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
+
+ if (p_srvc_cb != NULL)
+ {
+ switch (disc_type)
+ {
+ case GATT_DISC_SRVC_ALL:
+ /* discover services result, add services into a service list */
+ bta_gattc_add_srvc_to_list(p_srvc_cb,
+ p_data->handle,
+ p_data->value.group_value.e_handle,
+ p_data->value.group_value.service_type,
+ TRUE);
+
+ break;
+ case GATT_DISC_SRVC_BY_UUID:
+ bta_gattc_add_srvc_to_list(p_srvc_cb,
+ p_data->handle,
+ p_data->value.handle,
+ p_data->type,
+ TRUE);
+ break;
+
+ case GATT_DISC_INC_SRVC:
+ /* add included service into service list if it's secondary or it never showed up
+ in the primary service search */
+ pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb,
+ p_data->value.incl_service.s_handle,
+ p_data->value.incl_service.e_handle,
+ p_data->value.incl_service.service_type);
+
+ if (!pri_srvc)
+ bta_gattc_add_srvc_to_list(p_srvc_cb,
+ p_data->value.incl_service.s_handle,
+ p_data->value.incl_service.e_handle,
+ p_data->value.incl_service.service_type,
+ FALSE);
+ /* add into database */
+ bta_gattc_add_attr_to_cache(p_srvc_cb,
+ p_data->handle,
+ &p_data->value.incl_service.service_type,
+ pri_srvc,
+ BTA_GATTC_ATTR_TYPE_INCL_SRVC);
+ break;
+
+ case GATT_DISC_CHAR:
+ /* add char value into database */
+ bta_gattc_add_char_to_list(p_srvc_cb,
+ p_data->handle,
+ p_data->value.dclr_value.val_handle,
+ p_data->value.dclr_value.char_uuid,
+ p_data->value.dclr_value.char_prop);
+ break;
+
+ case GATT_DISC_CHAR_DSCPT:
+ bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0, BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
+ break;
+ }
+ }
+}
+void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
+{
+ tBTA_GATTC_SERV * p_srvc_cb;
+
+ p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
+
+ if (p_srvc_cb != NULL)
+ {
+ switch (disc_type)
+ {
+ case GATT_DISC_SRVC_ALL:
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
+#endif
+ bta_gattc_explore_srvc(conn_id, p_srvc_cb);
+ break;
+
+ case GATT_DISC_INC_SRVC:
+ bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
+
+ break;
+
+ case GATT_DISC_CHAR:
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
+#endif
+ bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
+ break;
+
+ case GATT_DISC_CHAR_DSCPT:
+ bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+ break;
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_id2handle
+**
+** Description map GATT ID to handle in a given cache.
+**
+** Returns the handle mapped. 0 if not found.
+**
+*******************************************************************************/
+UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id,
+ tBTA_GATT_ID *p_char_id, tBT_UUID descr_uuid)
+{
+ tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache;
+ tBTA_GATTC_CACHE_ATTR *p_attr;
+ UINT8 j;
+ UINT16 handle = 0;
+ tBT_UUID attr_uuid;
+ BOOLEAN char_map = FALSE, done = FALSE;
+
+ while (p_cache && !done)
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]",
+ p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
+ p_cache->service_uuid.id.inst_id);
+#endif
+ p_attr = p_cache->p_attr;
+
+ if (bta_gattc_uuid_compare(p_service_id->id.uuid, p_cache->service_uuid.id.uuid, TRUE) &&
+ p_service_id->id.inst_id == p_cache->service_uuid.id.inst_id &&
+ p_cache->service_uuid.is_primary == p_service_id->is_primary)
+ {
+ for (j = 0; p_attr; j ++)
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+ j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type);
+#endif
+ bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
+
+ if (bta_gattc_uuid_compare(p_char_id->uuid, attr_uuid, TRUE) &&
+ p_char_id->inst_id == p_attr->inst_id)
+ {
+ if (descr_uuid.len == 0)
+ {
+ handle = p_attr->attr_handle;
+ done = TRUE;
+ break;
+ }
+ else
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("found matching characteristic for the descriptor");
+#endif
+ char_map = TRUE;
+ }
+ }
+ else if (char_map == TRUE)
+ {
+ if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+ {
+
+ if (bta_gattc_uuid_compare(descr_uuid, attr_uuid, TRUE))
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("found descripotor!!");
+#endif
+ handle = p_attr->attr_handle;
+ done = TRUE;
+ break;
+ }
+ else
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("descriptor UUID not matching");
+#endif
+ }
+ }
+ else /* another char */
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("no matching descriptor found!! start of next characteristic");
+#endif
+ char_map = FALSE;
+ done = TRUE;
+ break;
+ }
+ }
+ p_attr = p_attr->p_next;
+ }
+ }
+ p_cache = p_cache->p_next;
+ }
+
+ return handle;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_handle2id
+**
+** Description map a handle to GATT ID in a given cache.
+**
+** Returns FALSE if map can not be found.
+**
+*******************************************************************************/
+
+BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
+ tBTA_GATT_ID *p_char_id, tBT_UUID *p_descr_type)
+{
+ tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache;
+ tBTA_GATTC_CACHE_ATTR *p_attr, *p_char = NULL;
+ UINT8 j;
+
+ memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
+ memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
+ memset(p_descr_type, 0, sizeof(tBT_UUID));
+
+ while (p_cache)
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]",
+ p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
+ p_cache->service_uuid.id.inst_id);
+#endif
+ /* a service found */
+ if (p_cache->s_handle == handle)
+ {
+ memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+
+ return TRUE;
+ }
+ else /* start looking for attributes within the service */
+ {
+ p_attr = p_cache->p_attr;
+
+ for (j = 0; p_attr; j ++)
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+ j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type);
+#endif
+ if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
+ p_char = p_attr;
+
+ if (handle == p_attr->attr_handle)
+ {
+ memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+
+ if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+ {
+ bta_gattc_pack_attr_uuid(p_attr, p_descr_type);
+
+ if (p_char != NULL)
+ {
+ bta_gattc_pack_attr_uuid(p_char, &p_char_id->uuid);
+ p_char_id->inst_id = p_char->inst_id;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("descriptor does not belong to any chracteristic, error");
+ }
+ }
+ else
+ /* is a characterisitc value or included service */
+ {
+ bta_gattc_pack_attr_uuid(p_attr, &p_char_id->uuid);
+ p_char_id->inst_id =p_attr->inst_id;
+ }
+ return TRUE;
+ }
+ p_attr = p_attr->p_next;
+ }
+ }
+ p_cache = p_cache->p_next;
+ }
+
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_search_service
+**
+** Description search local cache for matching service record.
+**
+** Returns FALSE if map can not be found.
+**
+*******************************************************************************/
+void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid)
+{
+ tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb;
+ tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache;
+ tBTA_GATTC cb_data;
+
+ while (p_cache)
+ {
+ if (bta_gattc_uuid_compare(uuid, p_cache->service_uuid.id.uuid, FALSE))
+ {
+//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG3("found service [0x%04x], inst[%d] handle [%d]",
+ p_cache->service_uuid.id.uuid.uu.uuid16,
+ p_cache->service_uuid.id.inst_id,
+ p_cache->s_handle);
+//#endif
+ if (p_clcb->p_rcb->p_cback)
+ {
+ memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+ cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
+ memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid ,sizeof(tBTA_GATT_SRVC_ID));
+
+ (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
+ //todo (tBTA_GATTC *)&p_cache->service_uuid);
+ }
+ }
+ p_cache = p_cache->p_next;
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_find_record
+**
+** Description search local cache for matching attribute record.
+**
+** Parameter p_result: output parameter to store the characteristic/
+** included service GATT ID.
+**
+** Returns GATT_ERROR is no recording found. BTA_GATT_OK if record found.
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
+ tBTA_GATTC_ATTR_TYPE attr_type,
+ tBTA_GATT_SRVC_ID *p_service_id,
+ tBTA_GATT_ID *p_start_rec,
+ tBT_UUID * p_uuid_cond,
+ tBTA_GATT_ID *p_result,
+ void *p_param)
+{
+ tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache;
+ tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+ tBT_UUID uuid_cond = {0}, start_descr = {0};
+ UINT8 i, j;
+ tBTA_GATTC_CACHE_ATTR *p_attr;
+ BOOLEAN char_found = FALSE, descr_found = FALSE;
+
+ if (p_uuid_cond)
+ memcpy(&uuid_cond, p_uuid_cond, sizeof(tBT_UUID));
+
+ for (i = 0; p_cache <= p_srcb->p_cur_srvc && p_cache && status != BTA_GATT_OK; i ++)
+ {
+ if (bta_gattc_uuid_compare(p_service_id->id.uuid, p_cache->service_uuid.id.uuid, FALSE) &&
+ p_service_id->id.inst_id == p_cache->service_uuid.id.inst_id &&
+ p_service_id->is_primary == p_cache->service_uuid.is_primary)
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG2("found matching service [0x%04x], inst[%d]",
+ p_cache->service_uuid.id.uuid.uu.uuid16,
+ p_cache->service_uuid.id.inst_id);
+#endif
+ p_attr = p_cache->p_attr;
+
+ for (j = 0; p_attr; j ++)
+ {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+ APPL_TRACE_DEBUG5("\t Attr[%d] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+ j + 1, p_attr->attr_handle,
+ p_attr->p_uuid->uuid16,
+ p_attr->inst_id,
+ p_attr->attr_type);
+#endif
+ bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid);
+
+ if (p_start_rec != NULL && char_found == FALSE)
+ {
+ /* find the starting record first */
+ if (bta_gattc_uuid_compare(p_start_rec->uuid, p_result->uuid, FALSE) &&
+ p_start_rec->inst_id == p_attr->inst_id &&
+ (attr_type == p_attr->attr_type ||
+ /* find descriptor would look for characteristic first */
+ (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR && p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
+ {
+ char_found = TRUE;
+ }
+ }
+ else
+ {
+ /* if looking for descriptor, here is the where the descrptor to be found */
+ if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+ {
+ /* starting descriptor UUID */
+ if (p_param != NULL)
+ memcpy(&start_descr, p_param, sizeof(tBT_UUID));
+ /* next characeteristic already, return error */
+ if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+ {
+ break;
+ }
+ else
+ {
+ if (start_descr.len != 0 && !descr_found)
+ {
+ if (bta_gattc_uuid_compare(start_descr, p_result->uuid, FALSE))
+ {
+ descr_found = TRUE;
+ }
+ }
+ else
+ {
+ /* with matching descriptor */
+ if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE))
+ {
+ status = BTA_GATT_OK;
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE) &&
+ attr_type == p_attr->attr_type)
+ {
+
+ APPL_TRACE_DEBUG0("found char handle mapping characteristic");
+ p_result->inst_id = p_attr->inst_id;
+
+ if (p_param != NULL)
+ {
+ if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
+ attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC)
+ {
+ *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
+ }
+ }
+
+ status = BTA_GATT_OK;
+ break;
+ }
+ }
+ }
+ p_attr = p_attr->p_next;
+ }
+ if (status)
+ {
+ APPL_TRACE_ERROR0("In the given service, can not find matching record");
+ }
+ break;
+ }
+
+ p_cache = p_cache->p_next;
+ }
+ return status;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_query_cache
+**
+** Description search local cache for matching attribute record.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_srvc_id: the service ID of which the characteristic is belonged to.
+** *p_start_rec: start the search from the next record
+** after the one identified by *p_start_rec.
+** p_uuid_cond: UUID, if NULL find the first available
+** characteristic/included service.
+** p_output: output parameter which will store the GATT ID
+** of the characteristic /included service found.
+**
+** Returns BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
+ tBTA_GATTC_ATTR_TYPE query_type,
+ tBTA_GATT_SRVC_ID *p_srvc_id,
+ tBTA_GATT_ID *p_start_rec,
+ tBT_UUID *p_uuid_cond,
+ tBTA_GATT_ID *p_output,
+ void *p_param)
+{
+ tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+ tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
+
+ /* lock other GKI task */
+ GKI_sched_lock();
+
+ APPL_TRACE_DEBUG0("bta_gattc_query_cache");
+
+ if (p_clcb != NULL )
+ {
+ if (p_clcb->state == BTA_GATTC_CONN_ST)
+ {
+ if (p_clcb->p_srcb &&
+ !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
+ p_clcb->p_srcb->p_srvc_cache)
+ {
+ status = bta_gattc_find_record(p_clcb->p_srcb,
+ query_type,
+ p_srvc_id,
+ p_start_rec,
+ p_uuid_cond,
+ p_output,
+ p_param);
+ }
+ else
+ {
+ status = BTA_GATT_ERROR;
+ APPL_TRACE_ERROR0("No server cache available");
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("server cache not available, CLCB state = %d", p_clcb->state);
+
+ status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Unknown conn ID: %d", conn_id);
+ }
+ GKI_sched_unlock();
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_rebuild_cache
+**
+** Description rebuild server cache from NV cache.
+**
+** Parameters
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
+ tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index)
+{
+ /* first attribute loading, initialize buffer */
+ APPL_TRACE_ERROR0("bta_gattc_rebuild_cache");
+ if (attr_index == 0)
+ {
+ while (p_srvc_cb->cache_buffer.p_first)
+ GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+ if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+ {
+ APPL_TRACE_ERROR0("allocate cache buffer failed, no resources");
+ }
+ else
+ {
+ p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
+ }
+ }
+
+ while (num_attr > 0 && p_attr != NULL)
+ {
+ switch (p_attr->attr_type)
+ {
+ case BTA_GATTC_ATTR_TYPE_SRVC:
+ bta_gattc_add_srvc_to_cache(p_srvc_cb,
+ p_attr->s_handle,
+ p_attr->e_handle,
+ &p_attr->uuid,
+ p_attr->is_primary,
+ p_attr->id);
+ break;
+
+ case BTA_GATTC_ATTR_TYPE_CHAR:
+ case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
+ case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
+ bta_gattc_add_attr_to_cache(p_srvc_cb,
+ p_attr->s_handle,
+ &p_attr->uuid,
+ p_attr->prop,
+ p_attr->attr_type);
+ break;
+ }
+ p_attr ++;
+ num_attr --;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_fill_nv_attr
+**
+** Description fill a NV attribute entry value
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
+ UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop, BOOLEAN is_primary)
+{
+ p_attr->s_handle = s_handle;
+ p_attr->e_handle = e_handle;
+ p_attr->attr_type = type;
+ p_attr->is_primary = is_primary;
+ p_attr->id = id;
+ p_attr->prop = prop;
+
+ memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
+}
+/*******************************************************************************
+**
+** Function bta_gattc_cache_save
+**
+** Description save the server cache into NV
+**
+** Returns None.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
+{
+ tBTA_GATTC_CACHE *p_cur_srvc = p_srvc_cb->p_srvc_cache;
+ UINT8 i = 0;
+ UINT16 offset = 0;
+ tBTA_GATTC_NV_ATTR nv_attr[BTA_GATTC_NV_LOAD_MAX];
+ tBTA_GATTC_CACHE_ATTR *p_attr;
+ tBT_UUID uuid;
+
+ while (p_cur_srvc && i < BTA_GATTC_NV_LOAD_MAX)
+ {
+ if (offset ++ >= p_srvc_cb->attr_index)
+ {
+ bta_gattc_fill_nv_attr(&nv_attr[i++],
+ BTA_GATTC_ATTR_TYPE_SRVC,
+ p_cur_srvc->s_handle,
+ p_cur_srvc->e_handle,
+ p_cur_srvc->service_uuid.id.inst_id,
+ p_cur_srvc->service_uuid.id.uuid,
+ 0,
+ p_cur_srvc->service_uuid.is_primary);
+ }
+
+ p_attr = p_cur_srvc->p_attr;
+
+ for (; p_attr && i < BTA_GATTC_NV_LOAD_MAX ; offset ++, p_attr = p_attr->p_next)
+ {
+ if (offset >= p_srvc_cb->attr_index)
+ {
+ if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16)
+ {
+ uuid.uu.uuid16 = p_attr->p_uuid->uuid16;
+ }
+ else
+ {
+ memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128);
+ }
+
+ bta_gattc_fill_nv_attr(&nv_attr[i++],
+ p_attr->attr_type,
+ p_attr->attr_handle,
+ 0,
+ p_attr->inst_id,
+ uuid,
+ p_attr->property,
+ FALSE);
+ }
+ }
+ p_cur_srvc = p_cur_srvc->p_next;
+ }
+
+ if (i > 0)
+ {
+ bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i,
+ nv_attr, p_srvc_cb->attr_index, conn_id);
+
+ p_srvc_cb->attr_index += i;
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+#endif /* BTA_GATT_INCLUDED */
+
diff --git a/bta/gatt/bta_gattc_ci.c b/bta/gatt/bta_gattc_ci.c
new file mode 100644
index 0000000..212126f
--- /dev/null
+++ b/bta/gatt/bta_gattc_ci.c
@@ -0,0 +1,137 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation file for the GATT call-in functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_gattc_ci.h"
+#include "gki.h"
+#include "bd.h"
+
+/*******************************************************************************
+**
+** Function bta_gattc_ci_cache_open
+**
+** Description This function sends an event to indicate server cache open
+** completed.
+**
+** Parameters server_bda - server BDA of this cache.
+** status - BTA_GATT_OK if full buffer of data,
+** BTA_GATT_FAIL if an error has occurred.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_open(BD_ADDR server_bda, UINT16 evt, tBTA_GATT_STATUS status,
+ UINT16 conn_id)
+{
+ tBTA_GATTC_CI_EVT *p_evt;
+
+ if ((p_evt = (tBTA_GATTC_CI_EVT *) GKI_getbuf(sizeof(tBTA_GATTC_CI_EVT))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->hdr.layer_specific = conn_id;
+
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_ci_cache_load
+**
+** Description This function sends an event to BTA indicating the phone has
+** load the servere cache and ready to send it to the stack.
+**
+** Parameters server_bda - server BDA of this cache.
+** num_bytes_read - number of bytes read into the buffer
+** specified in the read callout-function.
+** status - BTA_GATT_OK if full buffer of data,
+** BTA_GATT_FAIL if an error has occurred.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
+ tBTA_GATTC_NV_ATTR *p_attr, tBTA_GATT_STATUS status,
+ UINT16 conn_id)
+{
+ tBTA_GATTC_CI_LOAD *p_evt;
+
+ if ((p_evt = (tBTA_GATTC_CI_LOAD *) GKI_getbuf(sizeof(tBTA_GATTC_CI_LOAD))) != NULL)
+ {
+ memset(p_evt, 0, sizeof(tBTA_GATTC_CI_LOAD));
+
+ p_evt->hdr.event = evt;
+ p_evt->hdr.layer_specific = conn_id;
+
+ p_evt->status = status;
+ p_evt->num_attr = (num_attr > BTA_GATTC_NV_LOAD_MAX) ? BTA_GATTC_NV_LOAD_MAX : num_attr;
+
+ if (p_evt->num_attr > 0 && p_attr != NULL)
+ {
+ memcpy(p_evt->attr, p_attr, p_evt->num_attr * sizeof(tBTA_GATTC_NV_ATTR));
+ }
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_ci_cache_save
+**
+** Description This function sends an event to BTA indicating the phone has
+** save the servere cache.
+**
+** Parameters server_bda - server BDA of this cache.
+** evt - callin event code.
+** status - BTA_GATT_OK if full buffer of data,
+** BTA_GATT_ERROR if an error has occurred.
+*8 conn_id - for this NV operation for.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_save(BD_ADDR server_bda, UINT16 evt, tBTA_GATT_STATUS status,
+ UINT16 conn_id)
+{
+ tBTA_GATTC_CI_EVT *p_evt;
+
+ if ((p_evt = (tBTA_GATTC_CI_EVT *) GKI_getbuf(sizeof(tBTA_GATTC_CI_EVT))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->hdr.layer_specific = conn_id;
+
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
new file mode 100644
index 0000000..407e5d8
--- /dev/null
+++ b/bta/gatt/bta_gattc_int.h
@@ -0,0 +1,464 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private file for the file transfer client (FTC).
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_INT_H
+#define BTA_GATTC_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gattc_ci.h"
+#include "bta_gattc_co.h"
+
+#include "gki.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+enum
+{
+ BTA_GATTC_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_GATTC),
+ BTA_GATTC_INT_OPEN_FAIL_EVT,
+ BTA_GATTC_API_CANCEL_OPEN_EVT,
+ BTA_GATTC_INT_CANCEL_OPEN_OK_EVT,
+
+ BTA_GATTC_API_READ_EVT,
+ BTA_GATTC_API_WRITE_EVT,
+ BTA_GATTC_API_EXEC_EVT,
+
+ BTA_GATTC_API_CLOSE_EVT,
+
+ BTA_GATTC_API_SEARCH_EVT,
+ BTA_GATTC_API_CONFIRM_EVT,
+ BTA_GATTC_API_READ_MULTI_EVT,
+
+ BTA_GATTC_INT_CONN_EVT,
+ BTA_GATTC_INT_DISCOVER_EVT,
+ BTA_GATTC_DISCOVER_CMPL_EVT,
+ BTA_GATTC_OP_CMPL_EVT,
+ BTA_GATTC_INT_DISCONN_EVT,
+
+ /* for cache loading/saving */
+ BTA_GATTC_START_CACHE_EVT,
+ BTA_GATTC_CI_CACHE_OPEN_EVT,
+ BTA_GATTC_CI_CACHE_LOAD_EVT,
+ BTA_GATTC_CI_CACHE_SAVE_EVT,
+
+ BTA_GATTC_INT_START_IF_EVT,
+ BTA_GATTC_API_REG_EVT,
+ BTA_GATTC_API_DEREG_EVT,
+ BTA_GATTC_INT_DEREG_EVT
+
+};
+typedef UINT16 tBTA_GATTC_INT_EVT;
+
+/* max client application GATTC can support */
+#ifndef BTA_GATTC_CL_MAX
+#define BTA_GATTC_CL_MAX 4
+#endif
+
+/* max known devices GATTC can support */
+#ifndef BTA_GATTC_KNOWN_SR_MAX
+#define BTA_GATTC_KNOWN_SR_MAX 4
+#endif
+
+#ifndef BTA_GATTC_CLCB_MAX
+ #define BTA_GATTC_CLCB_MAX GATT_CL_MAX_LCB
+#endif
+
+#define BTA_GATTC_WRITE_PREPARE GATT_WRITE_PREPARE
+
+/* internal strucutre for GATTC register API */
+typedef struct
+{
+ BT_HDR hdr;
+ tBT_UUID app_uuid;
+ tBTA_GATTC_CBACK *p_cback;
+}tBTA_GATTC_API_REG;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATTC_IF client_if;
+}tBTA_GATTC_INT_START_IF;
+
+typedef tBTA_GATTC_INT_START_IF tBTA_GATTC_API_DEREG;
+typedef tBTA_GATTC_INT_START_IF tBTA_GATTC_INT_DEREG;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR remote_bda;
+ tBTA_GATTC_IF client_if;
+ BOOLEAN is_direct;
+} tBTA_GATTC_API_OPEN;
+
+typedef tBTA_GATTC_API_OPEN tBTA_GATTC_API_CANCEL_OPEN;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATT_AUTH_REQ auth_req;
+ tBTA_GATT_SRVC_ID srvc_id;
+ tBTA_GATT_ID char_id;
+ tBT_UUID descr_type;
+} tBTA_GATTC_API_READ;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATT_AUTH_REQ auth_req;
+ tBTA_GATT_SRVC_ID srvc_id;
+ tBTA_GATT_ID char_id;
+ tBT_UUID descr_type;
+ tBTA_GATTC_WRITE_TYPE write_type;
+ UINT16 offset;
+ UINT16 len;
+ UINT8 *p_value;
+}tBTA_GATTC_API_WRITE;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN is_execute;
+}tBTA_GATTC_API_EXEC;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATT_SRVC_ID srvc_id;
+ tBTA_GATT_ID char_id;
+} tBTA_GATTC_API_CONFIRM;
+
+typedef tGATT_CL_COMPLETE tBTA_GATTC_CMPL;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 op_code;
+ tGATT_STATUS status;
+ tBTA_GATTC_CMPL *p_cmpl;
+}tBTA_GATTC_OP_CMPL;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBT_UUID srvc_uuid;
+}tBTA_GATTC_API_SEARCH;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATT_AUTH_REQ auth_req;
+ UINT8 num_attr;
+ tBTA_GATTC_ATTR_ID *p_id_list;
+}tBTA_GATTC_API_READ_MULTI;
+
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_GATTC_API_REG api_reg;
+ tBTA_GATTC_API_DEREG api_dereg;
+ tBTA_GATTC_API_OPEN api_conn;
+ tBTA_GATTC_API_CANCEL_OPEN api_cancel_conn;
+ tBTA_GATTC_API_READ api_read;
+ tBTA_GATTC_API_SEARCH api_search;
+ tBTA_GATTC_API_WRITE api_write;
+ tBTA_GATTC_API_CONFIRM api_confirm;
+ tBTA_GATTC_API_EXEC api_exec;
+ tBTA_GATTC_API_READ_MULTI api_read_multi;
+ tBTA_GATTC_OP_CMPL op_cmpl;
+ tBTA_GATTC_CI_EVT ci_open;
+ tBTA_GATTC_CI_EVT ci_save;
+ tBTA_GATTC_CI_LOAD ci_load;
+
+ tBTA_GATTC_INT_START_IF int_start_if;
+ tBTA_GATTC_INT_DEREG int_dereg;
+
+} tBTA_GATTC_DATA;
+
+
+/* GATT server cache on the client */
+typedef union
+{
+ UINT8 uuid128[LEN_UUID_128];
+ UINT16 uuid16;
+}tBTA_GATTC_UUID;
+
+typedef struct gattc_attr_cache
+{
+ tBTA_GATTC_UUID *p_uuid;
+ struct gattc_attr_cache *p_next;
+ UINT16 uuid_len;
+ UINT16 attr_handle;
+ UINT8 inst_id;
+ tBTA_GATT_CHAR_PROP property; /* if characteristic, it is char property;
+ if included service, flag primary,
+ if descriptor, not used */
+ tBTA_GATTC_ATTR_TYPE attr_type;
+// btla-specific ++
+} __attribute__((packed)) tBTA_GATTC_CACHE_ATTR;
+// btla-specific --
+
+typedef struct gattc_svc_cache
+{
+ tBTA_GATT_SRVC_ID service_uuid;
+ tBTA_GATTC_CACHE_ATTR *p_attr;
+ tBTA_GATTC_CACHE_ATTR *p_last_attr;
+ UINT16 s_handle;
+ UINT16 e_handle;
+ struct gattc_svc_cache *p_next;
+// btla-specific ++
+} __attribute__((packed)) tBTA_GATTC_CACHE;
+// btla-specific --
+
+typedef struct
+{
+ tBT_UUID uuid;
+ UINT16 s_handle;
+ UINT16 e_handle;
+ BOOLEAN is_primary;
+ UINT8 srvc_inst_id;
+ tBTA_GATT_CHAR_PROP property;
+}tBTA_GATTC_ATTR_REC;
+
+
+#define BTA_GATTC_MAX_CACHE_CHAR 40
+#define BTA_GATTC_ATTR_LIST_SIZE (BTA_GATTC_MAX_CACHE_CHAR * sizeof(tBTA_GATTC_ATTR_REC))
+
+#ifndef BTA_GATTC_CACHE_SRVR_SIZE
+ #define BTA_GATTC_CACHE_SRVR_SIZE 600
+#endif
+
+enum
+{
+ BTA_GATTC_IDLE_ST = 0, /* Idle */
+ BTA_GATTC_W4_CONN_ST, /* Wait for connection - (optional) */
+ BTA_GATTC_CONN_ST, /* connected state */
+ BTA_GATTC_DISCOVER_ST /* discover is in progress */
+};
+typedef UINT8 tBTA_GATTC_STATE;
+
+typedef struct
+{
+ BOOLEAN in_use;
+ BD_ADDR server_bda;
+ BOOLEAN connected;
+
+#define BTA_GATTC_SERV_IDLE 0
+#define BTA_GATTC_SERV_LOAD 1
+#define BTA_GATTC_SERV_SAVE 2
+
+ UINT8 state;
+
+ tBTA_GATTC_CACHE *p_srvc_cache;
+ tBTA_GATTC_CACHE *p_cur_srvc;
+ BUFFER_Q cache_buffer; /* buffer queue used for storing the cache data */
+ UINT8 *p_free; /* starting point to next available byte */
+ UINT16 free_byte; /* number of available bytes in server cache buffer */
+ UINT8 update_count; /* indication received */
+ UINT8 num_clcb; /* number of associated CLCB */
+
+
+ tBTA_GATTC_ATTR_REC *p_srvc_list;
+ UINT8 cur_srvc_idx;
+ UINT8 cur_char_idx;
+ UINT8 next_avail_idx;
+ UINT8 total_srvc;
+ UINT8 total_char;
+
+ UINT8 srvc_hdl_chg; /* service handle change indication pending */
+ UINT16 attr_index; /* cahce NV saving/loading attribute index */
+
+} tBTA_GATTC_SERV;
+
+#ifndef BTA_GATTC_NOTIF_REG_MAX
+#define BTA_GATTC_NOTIF_REG_MAX 4
+#endif
+
+typedef struct
+{
+ BOOLEAN in_use;
+ BD_ADDR remote_bda;
+ tBTA_GATTC_CHAR_ID char_id;
+}tBTA_GATTC_NOTIF_REG;
+
+typedef struct
+{
+ tBTA_GATTC_CBACK *p_cback;
+ BOOLEAN in_use;
+ tBTA_GATTC_IF client_if; /* client interface with BTE stack for this application */
+ UINT8 num_clcb; /* number of associated CLCB */
+ BOOLEAN dereg_pending;
+ tBT_UUID app_uuid;
+ tBTA_GATTC_NOTIF_REG notif_reg[BTA_GATTC_NOTIF_REG_MAX];
+}tBTA_GATTC_RCB;
+
+/* client channel is a mapping between a BTA client(cl_id) and a remote BD address */
+typedef struct
+{
+ UINT16 bta_conn_id; /* client channel ID, unique for clcb */
+ BD_ADDR bda;
+ tBTA_GATTC_RCB *p_rcb; /* pointer to the registration CB */
+ tBTA_GATTC_SERV *p_srcb; /* server cache CB */
+ tBTA_GATTC_DATA *p_q_cmd; /* command in queue waiting for execution */
+
+#define BTA_GATTC_NO_SCHEDULE 0
+#define BTA_GATTC_DISC_WAITING 0x01
+#define BTA_GATTC_REQ_WAITING 0x10
+
+ UINT8 auto_update; /* auto update is waiting */
+ BOOLEAN in_use;
+ tBTA_GATTC_STATE state;
+ tBTA_GATT_STATUS status;
+ UINT16 reason;
+} tBTA_GATTC_CLCB;
+
+/* back ground connection tracking information */
+#if GATT_MAX_APPS <= 8
+typedef UINT8 tBTA_GATTC_CIF_MASK ;
+#elif GATT_MAX_APPS <= 16
+typedef UINT16 tBTA_GATTC_CIF_MASK;
+#elif GATT_MAX_APPS <= 32
+typedef UINT32 tBTA_GATTC_CIF_MASK;
+#endif
+
+typedef struct
+{
+ BOOLEAN in_use;
+ BD_ADDR remote_bda;
+ tBTA_GATTC_CIF_MASK cif_mask;
+
+}tBTA_GATTC_BG_TCK;
+
+typedef struct
+{
+ tBTA_GATTC_BG_TCK bg_track[BTA_GATTC_KNOWN_SR_MAX];
+ tBTA_GATTC_RCB cl_rcb[BTA_GATTC_CL_MAX];
+
+ tBTA_GATTC_CLCB clcb[BTA_GATTC_CLCB_MAX];
+ tBTA_GATTC_SERV known_server[BTA_GATTC_KNOWN_SR_MAX];
+
+ tSDP_DISCOVERY_DB *p_sdp_db;
+ UINT16 sdp_conn_id;
+}tBTA_GATTC_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTC_CB bta_gattc_cb;
+#else
+extern tBTA_GATTC_CB *bta_gattc_cb_ptr;
+#define bta_gattc_cb (*bta_gattc_cb_ptr)
+#endif
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg);
+extern void bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data);
+
+/* function processed outside SM */
+extern void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_int_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+
+/* function within state machine */
+extern void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_open_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg);
+extern void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data);
+extern void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
+ BD_ADDR remote_bda, UINT16 conn_id);
+
+/* utility functions */
+extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda); //todo
+extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id);
+extern tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda);
+extern void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb);
+extern tBTA_GATTC_CLCB * bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda);
+extern tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if);
+extern tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda);
+extern tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda);
+extern tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id);
+extern BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id, tBTA_GATT_ID *p_char_id, tBT_UUID descr_uuid);
+extern BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *service_id, tBTA_GATT_ID *char_id, tBT_UUID *p_type);
+extern BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_precise);
+extern void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR *p_attr, tBT_UUID *p_uuid);
+extern BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_SERV *p_srcb, tBTA_GATTC_NOTIFY *p_notify);
+extern tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid, tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value);
+extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN add);
+extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda);
+extern UINT8 bta_gattc_num_reg_app(void);
+extern void bta_gattc_clear_notif_registration(UINT16 conn_id);
+
+/* discovery functions */
+extern void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
+extern void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status);
+extern tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
+extern tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
+extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid);
+extern tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, UINT8 query_type, tBTA_GATT_SRVC_ID *p_srvc_id,
+ tBTA_GATT_ID *p_start_rec,tBT_UUID *p_uuid_cond,
+ tBTA_GATT_ID *p_output, void *p_property);
+extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
+extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index);
+extern BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
+
+#endif /* BTA_GATTC_INT_H */
diff --git a/bta/gatt/bta_gattc_main.c b/bta/gatt/bta_gattc_main.c
new file mode 100644
index 0000000..a1fb536
--- /dev/null
+++ b/bta/gatt/bta_gattc_main.c
@@ -0,0 +1,486 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the GATT client main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_gattc_int.h"
+#include "gki.h"
+
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_GATTC_OPEN,
+ BTA_GATTC_OPEN_FAIL,
+ //BTA_GATTC_OPEN_FAIL_IN_CONN, //<--- need to remove this?
+ BTA_GATTC_OPEN_ERROR,
+ BTA_GATTC_CANCEL_OPEN,
+ BTA_GATTC_CANCEL_OPEN_OK,
+ BTA_GATTC_CANCEL_OPEN_ERROR,
+ BTA_GATTC_CONN,
+ BTA_GATTC_START_DISCOVER,
+ BTA_GATTC_DISC_CMPL,
+
+ BTA_GATTC_Q_CMD,
+ BTA_GATTC_CLOSE,
+ BTA_GATTC_CLOSE_FAIL,
+ BTA_GATTC_READ,
+ BTA_GATTC_WRITE,
+
+ BTA_GATTC_OP_CMPL,
+ BTA_GATTC_SEARCH,
+ BTA_GATTC_FAIL,
+ BTA_GATTC_CONFIRM,
+ BTA_GATTC_EXEC,
+ BTA_GATTC_READ_MULTI,
+ BTA_GATTC_CI_OPEN,
+ BTA_GATTC_CI_LOAD,
+ BTA_GATTC_CI_SAVE,
+ BTA_GATTC_CACHE_OPEN,
+ BTA_GATTC_IGNORE_OP_CMPL,
+
+ BTA_GATTC_IGNORE
+};
+/* type for action functions */
+typedef void (*tBTA_GATTC_ACTION)(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+/* action function list */
+const tBTA_GATTC_ACTION bta_gattc_action[] =
+{
+ bta_gattc_open,
+ bta_gattc_open_fail,
+ //bta_gattc_open_fail_in_conn, //<--- need to remove this?
+ bta_gattc_open_error,
+ bta_gattc_cancel_open,
+ bta_gattc_cancel_open_ok,
+ bta_gattc_cancel_open_error,
+ bta_gattc_conn,
+ bta_gattc_start_discover,
+ bta_gattc_disc_cmpl,
+
+ bta_gattc_q_cmd,
+ bta_gattc_close,
+ bta_gattc_close_fail,
+ bta_gattc_read,
+ bta_gattc_write,
+
+ bta_gattc_op_cmpl,
+ bta_gattc_search,
+ bta_gattc_fail,
+ bta_gattc_confirm,
+ bta_gattc_execute,
+ bta_gattc_read_multi,
+ bta_gattc_ci_open,
+ bta_gattc_ci_load,
+ bta_gattc_ci_save,
+ bta_gattc_cache_open,
+ bta_gattc_ignore_op_cmpl
+};
+
+
+/* state table information */
+#define BTA_GATTC_ACTIONS 1 /* number of actions */
+#define BTA_GATTC_NEXT_STATE 1 /* position of next state */
+#define BTA_GATTC_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_gattc_st_idle[][BTA_GATTC_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_GATTC_API_OPEN_EVT */ {BTA_GATTC_OPEN, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_READ_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE_FAIL, BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_CONN, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+
+
+/* ===> for cache loading, saving */
+/* BTA_GATTC_START_CACHE_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_IDLE_ST}
+};
+
+/* state table for wait for open state */
+static const UINT8 bta_gattc_st_w4_conn[][BTA_GATTC_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_GATTC_API_OPEN_EVT */ {BTA_GATTC_OPEN, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT */ {BTA_GATTC_OPEN_FAIL, BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT */ {BTA_GATTC_CANCEL_OPEN, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */ {BTA_GATTC_CANCEL_OPEN_OK, BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_READ_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE_FAIL, BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_CONN, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving */
+/* BTA_GATTC_START_CACHE_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_W4_CONN_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_gattc_st_connected[][BTA_GATTC_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_GATTC_API_OPEN_EVT */ {BTA_GATTC_OPEN_ERROR, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT */ {BTA_GATTC_CANCEL_OPEN_ERROR, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_API_READ_EVT */ {BTA_GATTC_READ, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_WRITE, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_EXEC, BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST}, //BTA_GATTC_CLOSING_ST
+
+/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_SEARCH, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_CONFIRM, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_READ_MULTI, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_START_DISCOVER, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_OP_CMPL, BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving */
+/* BTA_GATTC_START_CACHE_EVT */ {BTA_GATTC_CACHE_OPEN, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_CONN_ST}
+};
+
+/* state table for discover state */
+static const UINT8 bta_gattc_st_discover[][BTA_GATTC_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_GATTC_API_OPEN_EVT */ {BTA_GATTC_OPEN_ERROR, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT */ {BTA_GATTC_CANCEL_OPEN_ERROR, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */ {BTA_GATTC_FAIL, BTA_GATTC_DISCOVER_ST},
+
+/* BTA_GATTC_API_READ_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_WRITE_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_EXEC_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST }, //BTA_GATTC_CLOSING_ST
+
+/* BTA_GATTC_API_SEARCH_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_CONFIRM_EVT */ {BTA_GATTC_CONFIRM, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT */ {BTA_GATTC_Q_CMD, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_CONN_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT */ {BTA_GATTC_START_DISCOVER, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT */ {BTA_GATTC_DISC_CMPL, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT */ {BTA_GATTC_IGNORE_OP_CMPL, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_DISCONN_EVT */ {BTA_GATTC_CLOSE, BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving */
+/* BTA_GATTC_START_CACHE_EVT */ {BTA_GATTC_IGNORE, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT */ {BTA_GATTC_CI_OPEN, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT */ {BTA_GATTC_CI_LOAD, BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT */ {BTA_GATTC_CI_SAVE, BTA_GATTC_DISCOVER_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_GATTC_ST_TBL)[BTA_GATTC_NUM_COLS];
+
+/* state table */
+const tBTA_GATTC_ST_TBL bta_gattc_st_tbl[] =
+{
+ bta_gattc_st_idle,
+ bta_gattc_st_w4_conn,
+ bta_gattc_st_connected,
+ bta_gattc_st_discover
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_GATTC_CB bta_gattc_cb;
+#endif
+
+#if BTA_GATT_DEBUG == TRUE
+static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code);
+static char *gattc_state_code(tBTA_GATTC_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_gattc_sm_execute
+**
+** Description State machine event handling function for GATTC
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data)
+{
+ tBTA_GATTC_ST_TBL state_table;
+ UINT8 action;
+ int i;
+#if BTA_GATT_DEBUG == TRUE
+ tBTA_GATTC_STATE in_state = p_clcb->state;
+ UINT16 in_event = event;
+ APPL_TRACE_DEBUG4("bta_gattc_sm_execute: State 0x%02x [%s], Event 0x%x[%s]", in_state,
+ gattc_state_code(in_state),
+ in_event,
+ gattc_evt_code(in_event));
+#endif
+
+
+ /* look up the state table for the current state */
+ state_table = bta_gattc_st_tbl[p_clcb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_clcb->state = state_table[event][BTA_GATTC_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_GATTC_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_GATTC_IGNORE)
+ {
+ (*bta_gattc_action[action])(p_clcb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+#if BTA_GATT_DEBUG == TRUE
+ if (in_state != p_clcb->state)
+ {
+ APPL_TRACE_DEBUG3("GATTC State Change: [%s] -> [%s] after Event [%s]",
+ gattc_state_code(in_state),
+ gattc_state_code(p_clcb->state),
+ gattc_evt_code(in_event));
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_hdl_event
+**
+** Description GATT client main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
+{
+ tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
+ tBTA_GATTC_CLCB *p_clcb = NULL;
+
+#if BTA_GATT_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event));
+#endif
+ switch (p_msg->event)
+ {
+ case BTA_GATTC_API_REG_EVT:
+ bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg);
+ break;
+
+ case BTA_GATTC_INT_START_IF_EVT:
+ bta_gattc_start_if(p_cb, (tBTA_GATTC_DATA *) p_msg);
+ break;
+
+ case BTA_GATTC_API_DEREG_EVT:
+ bta_gattc_deregister(p_cb, (tBTA_GATTC_DATA *) p_msg);
+ break;
+
+ case BTA_GATTC_INT_DEREG_EVT:
+ bta_gattc_int_deregister(p_cb, (tBTA_GATTC_DATA *) p_msg);
+ break;
+
+ case BTA_GATTC_API_OPEN_EVT:
+ bta_gattc_process_api_open(p_cb, (tBTA_GATTC_DATA *) p_msg);
+ break;
+
+ case BTA_GATTC_API_CANCEL_OPEN_EVT:
+ bta_gattc_process_api_open_cancel(p_cb, (tBTA_GATTC_DATA *) p_msg);
+ break;
+
+ default:
+ if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific))
+ != NULL)
+ {
+ bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA *) p_msg);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Unknown conn ID: %d", p_msg->layer_specific);
+ }
+
+ break;
+ }
+
+
+ return(TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_GATT_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function gattc_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code)
+{
+ switch (evt_code)
+ {
+ case BTA_GATTC_API_OPEN_EVT:
+ return "BTA_GATTC_API_OPEN_EVT";
+ case BTA_GATTC_INT_OPEN_FAIL_EVT:
+ return "BTA_GATTC_INT_OPEN_FAIL_EVT";
+ case BTA_GATTC_API_CANCEL_OPEN_EVT:
+ return "BTA_GATTC_API_CANCEL_OPEN_EVT";
+ case BTA_GATTC_INT_CANCEL_OPEN_OK_EVT:
+ return "BTA_GATTC_INT_CANCEL_OPEN_OK_EVT";
+ case BTA_GATTC_API_READ_EVT:
+ return "BTA_GATTC_API_READ_EVT";
+ case BTA_GATTC_API_WRITE_EVT:
+ return "BTA_GATTC_API_WRITE_EVT";
+ case BTA_GATTC_API_EXEC_EVT:
+ return "BTA_GATTC_API_EXEC_EVT";
+ case BTA_GATTC_API_CLOSE_EVT:
+ return "BTA_GATTC_API_CLOSE_EVT";
+ case BTA_GATTC_API_SEARCH_EVT:
+ return "BTA_GATTC_API_SEARCH_EVT";
+ case BTA_GATTC_API_CONFIRM_EVT:
+ return "BTA_GATTC_API_CONFIRM_EVT";
+ case BTA_GATTC_API_READ_MULTI_EVT:
+ return "BTA_GATTC_API_READ_MULTI_EVT";
+ case BTA_GATTC_INT_CONN_EVT:
+ return "BTA_GATTC_INT_CONN_EVT";
+ case BTA_GATTC_INT_DISCOVER_EVT:
+ return "BTA_GATTC_INT_DISCOVER_EVT";
+ case BTA_GATTC_DISCOVER_CMPL_EVT:
+ return "BTA_GATTC_DISCOVER_CMPL_EVT";
+ case BTA_GATTC_OP_CMPL_EVT:
+ return "BTA_GATTC_OP_CMPL_EVT";
+ case BTA_GATTC_INT_DISCONN_EVT:
+ return "BTA_GATTC_INT_DISCONN_EVT";
+ case BTA_GATTC_START_CACHE_EVT:
+ return "BTA_GATTC_START_CACHE_EVT";
+ case BTA_GATTC_CI_CACHE_OPEN_EVT:
+ return "BTA_GATTC_CI_CACHE_OPEN_EVT";
+ case BTA_GATTC_CI_CACHE_LOAD_EVT:
+ return "BTA_GATTC_CI_CACHE_LOAD_EVT";
+ case BTA_GATTC_CI_CACHE_SAVE_EVT:
+ return "BTA_GATTC_CI_CACHE_SAVE_EVT";
+ case BTA_GATTC_INT_START_IF_EVT:
+ return "BTA_GATTC_INT_START_IF_EVT";
+ case BTA_GATTC_API_REG_EVT:
+ return "BTA_GATTC_API_REG_EVT";
+ case BTA_GATTC_API_DEREG_EVT:
+ return "BTA_GATTC_API_DEREG_EVT";
+
+ default:
+ return "unknown GATTC event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function gattc_state_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *gattc_state_code(tBTA_GATTC_STATE state_code)
+{
+ switch (state_code)
+ {
+ case BTA_GATTC_IDLE_ST:
+ return "GATTC_IDLE_ST";
+ case BTA_GATTC_W4_CONN_ST:
+ return "GATTC_W4_CONN_ST";
+ case BTA_GATTC_CONN_ST:
+ return "GATTC_CONN_ST";
+ case BTA_GATTC_DISCOVER_ST:
+ return "GATTC_DISCOVER_ST";
+ default:
+ return "unknown GATTC state code";
+ }
+}
+
+#endif /* Debug Functions */
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_utils.c b/bta/gatt/bta_gattc_utils.c
new file mode 100644
index 0000000..a36e26c
--- /dev/null
+++ b/bta/gatt/bta_gattc_utils.c
@@ -0,0 +1,664 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the GATT client utility function.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gattc_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+
+static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/*******************************************************************************
+**
+** Function bta_gatt_convert_uuid16_to_uuid128
+**
+** Description Convert a 16 bits UUID to be an standard 128 bits one.
+**
+** Returns TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
+{
+ UINT8 *p = &uuid_128[LEN_UUID_128 - 4];
+
+ memcpy (uuid_128, base_uuid, LEN_UUID_128);
+
+ UINT16_TO_STREAM(p, uuid_16);
+}
+/*******************************************************************************
+**
+** Function bta_gattc_uuid_compare
+**
+** Description Compare two UUID to see if they are the same.
+**
+** Returns TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_precise)
+{
+ UINT8 su[LEN_UUID_128], tu[LEN_UUID_128];
+ UINT8 *ps, *pt;
+
+ /* any of the UUID is unspecified */
+ if (src.len == 0 || tar.len == 0)
+ {
+ if (is_precise)
+ return FALSE;
+ else
+ return TRUE;
+ }
+
+ /* If both are 16-bit, we can do a simple compare */
+ if (src.len == 2 && tar.len == 2)
+ {
+ return src.uu.uuid16 == tar.uu.uuid16;
+ }
+
+ /* One or both of the UUIDs is 128-bit */
+ if (src.len == LEN_UUID_16)
+ {
+ /* convert a 16 bits UUID to 128 bits value */
+ bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
+ ps = su;
+ }
+ else
+ ps = src.uu.uuid128;
+
+ if (tar.len == LEN_UUID_16)
+ {
+ /* convert a 16 bits UUID to 128 bits value */
+ bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
+ pt = tu;
+ }
+ else
+ pt = tar.uu.uuid128;
+
+ return(memcmp(ps, pt, LEN_UUID_128) == 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_cl_get_regcb
+**
+** Description get registration control block by client interface.
+**
+** Returns pointer to the regcb
+**
+*******************************************************************************/
+tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if)
+{
+ UINT8 i = 0;
+ tBTA_GATTC_RCB *p_clrcb = &bta_gattc_cb.cl_rcb[0];
+
+ for (i = 0; i < BTA_GATTC_CL_MAX; i ++, p_clrcb ++)
+ {
+ if (p_clrcb->in_use &&
+ p_clrcb->client_if == client_if)
+ return p_clrcb;
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_num_reg_app
+**
+** Description find the number of registered application.
+**
+** Returns pointer to the regcb
+**
+*******************************************************************************/
+UINT8 bta_gattc_num_reg_app(void)
+{
+ UINT8 i = 0, j = 0;
+
+ for (i = 0; i < BTA_GATTC_CL_MAX; i ++)
+ {
+ if (bta_gattc_cb.cl_rcb[i].in_use)
+ j ++;
+ }
+ return j;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_find_clcb_by_cif
+**
+** Description get clcb by client interface and remote bd adddress
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda)
+{
+ tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
+ UINT8 i;
+
+ for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+ {
+ if (p_clcb->in_use &&
+ p_clcb->p_rcb->client_if == client_if &&
+ p_clcb->p_srcb &&
+ bdcmp(p_clcb->p_srcb->server_bda, remote_bda) == 0)
+ return p_clcb;
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_find_clcb_by_conn_id
+**
+** Description get clcb by connection ID
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id)
+{
+ tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
+ UINT8 i;
+
+ for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+ {
+ if (p_clcb->in_use &&
+ p_clcb->bta_conn_id == conn_id)
+ return p_clcb;
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_clcb_alloc
+**
+** Description allocate CLCB
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
+{
+ UINT8 i_clcb = 0;
+ tBTA_GATTC_CLCB *p_clcb = NULL;
+
+ for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++)
+ {
+ if (!bta_gattc_cb.clcb[i_clcb].in_use)
+ {
+#if BTA_GATT_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_gattc_clcb_alloc: found clcb[%d] available",i_clcb);
+#endif
+ p_clcb = &bta_gattc_cb.clcb[i_clcb];
+ p_clcb->in_use = TRUE;
+ bdcpy(p_clcb->bda, remote_bda);
+
+ p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
+
+ if ((p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL)
+ p_clcb->p_srcb = bta_gattc_srcb_alloc(remote_bda);
+
+ if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL)
+ {
+ p_clcb->p_srcb->num_clcb ++;
+ p_clcb->p_rcb->num_clcb ++;
+ }
+ else
+ {
+ /* release this clcb if clcb or srcb allocation failed */
+ p_clcb->in_use = FALSE;
+ p_clcb = NULL;
+ }
+ break;
+ }
+ }
+ return p_clcb;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_find_alloc_clcb
+**
+** Description find or allocate CLCB if not found.
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
+{
+ tBTA_GATTC_CLCB *p_clcb ;
+
+ if ((p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda)) == NULL)
+ {
+ p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda);
+ }
+ return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_clcb_dealloc
+**
+** Description Deallocte a clcb
+**
+** Returns pointer to the clcb
+**
+*******************************************************************************/
+void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
+{
+
+ if (p_clcb)
+ {
+ if (p_clcb->p_srcb->num_clcb)
+ p_clcb->p_srcb->num_clcb --;
+
+ if (p_clcb->p_rcb->num_clcb)
+ p_clcb->p_rcb->num_clcb --;
+
+ utl_freebuf((void **)&p_clcb->p_q_cmd);
+
+ APPL_TRACE_ERROR2("bta_gattc_clcb_dealloc in_use=%d conn_id=%d",p_clcb->in_use, p_clcb->bta_conn_id);
+ memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_gattc_clcb_dealloc p_clcb=NULL");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_find_srcb
+**
+** Description find server cache by remote bd address
+**
+** Returns pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda)
+{
+ tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0];
+ UINT8 i;
+
+ for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++)
+ {
+ if (p_srcb->in_use && bdcmp(p_srcb->server_bda, bda) == 0)
+ return p_srcb;
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_find_scb_by_cid
+**
+** Description find server control block by connection ID
+**
+** Returns pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id)
+{
+ tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+ if (p_clcb)
+ return p_clcb->p_srcb;
+ else
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_srcb_alloc
+**
+** Description allocate server cache control block
+**
+** Returns pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda)
+{
+ tBTA_GATTC_SERV *p_tcb = &bta_gattc_cb.known_server[0],
+ *p_recycle = NULL;
+ BOOLEAN found = FALSE;
+ UINT8 i;
+
+ for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_tcb ++)
+ {
+ if (!p_tcb->in_use)
+ {
+ found = TRUE;
+ break;
+ }
+ else if (!p_tcb->connected)
+ {
+ p_recycle = p_tcb;
+ }
+ }
+
+ /* if not found, try to recycle one known device */
+ if (!found && !p_recycle)
+ p_tcb = NULL;
+ else if (p_recycle)
+ p_tcb = p_recycle;
+
+ if (p_tcb != NULL)
+ {
+ while (p_tcb->cache_buffer.p_first)
+ GKI_freebuf (GKI_dequeue (&p_tcb->cache_buffer));
+
+ utl_freebuf((void **)&p_tcb->p_srvc_list);
+ memset(p_tcb, 0 , sizeof(tBTA_GATTC_SERV));
+
+ p_tcb->in_use = TRUE;
+ bdcpy(p_tcb->server_bda, bda);
+ }
+ return p_tcb;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_enqueue
+**
+** Description enqueue a client request in clcb.
+**
+** Returns success or failure.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+ BOOLEAN in_q = FALSE;
+
+ if (p_clcb->p_q_cmd == NULL)
+ {
+ p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(sizeof(tBTA_GATTC_DATA));
+
+ if (p_data)
+ memcpy(p_clcb->p_q_cmd, p_data, sizeof(tBTA_GATTC_DATA));
+
+ in_q = TRUE;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("already has a pending command!!");
+ /* skip the callback now. ----- need to send callback ? */
+ }
+ return in_q;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_pack_attr_uuid
+**
+** Description pack UUID into a stream.
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR *p_attr, tBT_UUID *p_uuid)
+{
+ UINT8 *pp = (UINT8 *)p_attr->p_uuid;
+
+ memset(p_uuid, 0, sizeof(tBT_UUID));
+
+ p_uuid->len = p_attr->uuid_len;
+
+ if (p_attr->uuid_len == LEN_UUID_16)
+ {
+ STREAM_TO_UINT16(p_uuid->uu.uuid16, pp);
+ }
+ else
+ {
+ memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128);
+ }
+
+ return;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_check_notif_registry
+**
+** Description check if the service notificaition has been registered.
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_SERV *p_srcb,
+ tBTA_GATTC_NOTIFY *p_notify)
+{
+ UINT8 i;
+
+ for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+ {
+ if (p_clreg->notif_reg[i].in_use &&
+ bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 &&
+ (bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.srvc_id.id.uuid, p_notify->char_id.srvc_id.id.uuid, FALSE) &&
+ p_clreg->notif_reg[i].char_id.srvc_id.id.inst_id == p_notify->char_id.srvc_id.id.inst_id &&
+ p_clreg->notif_reg[i].char_id.srvc_id.is_primary == p_notify->char_id.srvc_id.is_primary &&
+ bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.char_id.uuid, p_notify->char_id.char_id.uuid, FALSE) &&
+ p_clreg->notif_reg[i].char_id.char_id.inst_id == p_notify->char_id.char_id.inst_id)
+ )
+ {
+ APPL_TRACE_DEBUG0("Notification registered!");
+ return TRUE;
+ }
+ }
+ return FALSE;
+
+}
+/*******************************************************************************
+**
+** Function bta_gattc_clear_notif_registration
+**
+** Description clear up the notification registration information by BD_ADDR.
+**
+** Returns None.
+**
+*******************************************************************************/
+void bta_gattc_clear_notif_registration(UINT16 conn_id)
+{
+ BD_ADDR remote_bda;
+ tBTA_GATTC_IF gatt_if;
+ tBTA_GATTC_RCB *p_clrcb ;
+ UINT8 i;
+
+ if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda))
+ {
+ if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL)
+ {
+ for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+ {
+ if (p_clrcb->notif_reg[i].in_use && !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
+ memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+ }
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("can not clear indication/notif registration for unknown app");
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_gattc_pack_cb_data
+**
+** Description pack the data from read response into callback data structure.
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid,
+ tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value)
+{
+ UINT8 i = 0, *pp = p_attr->value;
+ tBT_UUID uuid = {LEN_UUID_16, {GATT_UUID_CHAR_AGG_FORMAT}};
+ UINT16 handle;
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+ /* GATT_UUID_CHAR_AGG_FORMAT */
+ if (bta_gattc_uuid_compare (uuid, descr_uuid, TRUE))
+ {
+ while (p_attr->len >= 2 && i < BTA_GATTC_MULTI_MAX)
+ {
+ STREAM_TO_UINT16(handle, pp);
+
+ if (bta_gattc_handle2id(p_srcb,
+ handle,
+ &p_value->aggre_value.pre_format[i].char_id.srvc_id,
+ &p_value->aggre_value.pre_format[i].char_id.char_id,
+ &p_value->aggre_value.pre_format[i].descr_type) == FALSE)
+ {
+ status = BTA_GATT_INTERNAL_ERROR;
+ APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", handle);
+ break;
+ }
+ i ++;
+ p_attr->len -= 2;
+ }
+ p_value->aggre_value.num_pres_fmt = i;
+ }
+ else
+ {
+ /* all others, take as raw format */
+ p_value->unformat.len = p_attr->len;
+ p_value->unformat.p_value = p_attr->value;
+ }
+ return status;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_mark_bg_conn
+**
+** Description mark background connection status when a bg connection is initiated
+** or terminated.
+**
+** Returns TRUE if success; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN add)
+{
+ tBTA_GATTC_BG_TCK *p_bg_tck = &bta_gattc_cb.bg_track[0];
+ UINT8 i = 0;
+
+ for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+ {
+ if (p_bg_tck->in_use &&
+ bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
+ {
+ if (add)
+ /* mask on the cif bit */
+ p_bg_tck->cif_mask |= (1 <<(client_if - 1));
+ else
+ p_bg_tck->cif_mask &= (~(1 <<(client_if - 1)));
+
+ return TRUE;
+ }
+ }
+ if (!add)
+ {
+ APPL_TRACE_ERROR0("Do not find the bg connection mask for the remote device");
+ return FALSE;
+ }
+ else /* adding a new device mask */
+ {
+ for (i = 0, p_bg_tck = &bta_gattc_cb.bg_track[0];
+ i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+ {
+ if (!p_bg_tck->in_use)
+ {
+ p_bg_tck->in_use = TRUE;
+ bdcpy(p_bg_tck->remote_bda, remote_bda);
+ p_bg_tck->cif_mask = (1 <<(client_if - 1));
+ return TRUE;
+ }
+ }
+ APPL_TRACE_ERROR0("no available space to mark the bg connection status");
+ return FALSE;
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gattc_check_bg_conn
+**
+** Description check if this is a background connection background connection.
+**
+** Returns TRUE if success; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
+{
+ tBTA_GATTC_BG_TCK *p_bg_tck = &bta_gattc_cb.bg_track[0];
+ UINT8 i = 0;
+ BOOLEAN is_bg_conn = FALSE;
+
+ for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+ {
+ if (p_bg_tck->in_use &&
+ bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
+ {
+ if ((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0)
+ is_bg_conn = TRUE;
+ break;
+ }
+ }
+ return is_bg_conn;
+}
+/*******************************************************************************
+**
+** Function bta_gattc_send_open_cback
+**
+** Description send open callback
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
+ BD_ADDR remote_bda, UINT16 conn_id)
+{
+ tBTA_GATTC cb_data;
+
+ if (p_clreg->p_cback)
+ {
+ memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+ cb_data.open.status = status;
+ cb_data.open.client_if = p_clreg->client_if;
+ cb_data.open.conn_id = conn_id;
+ bdcpy(cb_data.open.remote_bda, remote_bda);
+
+ (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
+ }
+}
+
+
+
+
+
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
new file mode 100644
index 0000000..1b47598
--- /dev/null
+++ b/bta/gatt/bta_gatts_act.c
@@ -0,0 +1,798 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the GATT Server action functions for the state
+ * machine.
+ *
+ ******************************************************************************/
+
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatts_int.h"
+#include "bta_gatts_co.h"
+
+#include <string.h>
+
+static void bta_gatts_nv_save_cback(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
+static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp);
+
+static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void bta_gatts_send_request_cback (UINT16 conn_id,
+ UINT32 trans_id,
+ tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data);
+static tGATT_CBACK bta_gatts_cback =
+{
+ bta_gatts_conn_cback,
+ NULL,
+ NULL,
+ NULL,
+ bta_gatts_send_request_cback
+};
+
+tGATT_APPL_INFO bta_gatts_nv_cback =
+{
+ bta_gatts_nv_save_cback,
+ bta_gatts_nv_srv_chg_cback
+};
+
+/*******************************************************************************
+**
+** Function bta_gatts_nv_save_cback
+**
+** Description NV save callback function.
+**
+** Parameter is_add: true is to add a handle range; otherwise is to delete.
+** Returns none.
+**
+*******************************************************************************/
+static void bta_gatts_nv_save_cback(BOOLEAN is_add, tGATTS_HNDL_RANGE *p_hndl_range)
+{
+ bta_gatts_co_update_handle_range(is_add, (tBTA_GATTS_HNDL_RANGE *)p_hndl_range);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gatts_nv_srv_chg_cback
+**
+** Description NV save callback function.
+**
+** Parameter is_add: true is to add a handle range; otherwise is to delete.
+** Returns none.
+**
+*******************************************************************************/
+static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp)
+{
+ return bta_gatts_co_srv_chg((tBTA_GATTS_SRV_CHG_CMD) cmd,
+ (tBTA_GATTS_SRV_CHG_REQ *) p_req,
+ (tBTA_GATTS_SRV_CHG_RSP *) p_rsp);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gatts_enable
+**
+** Description enable BTA GATTS module.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_enable(tBTA_GATTS_CB *p_cb)
+{
+ UINT8 index=0;
+ tBTA_GATTS_HNDL_RANGE handle_range;
+
+ p_cb->enabled = TRUE;
+
+ APPL_TRACE_DEBUG0("bta_gatts_enable");
+ while ( bta_gatts_co_load_handle_range(index, &handle_range))
+ {
+ GATTS_AddHandleRange((tGATTS_HNDL_RANGE *)&handle_range);
+ memset(&handle_range, 0, sizeof(tGATTS_HNDL_RANGE));
+ index++;
+ }
+
+ APPL_TRACE_DEBUG1("bta_gatts_enable: num of handle range added=%d", index);
+
+ if (!GATTS_NVRegister(&bta_gatts_nv_cback))
+ {
+ APPL_TRACE_ERROR0("BTA GATTS NV register failed.");
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gatts_register
+**
+** Description register an application.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+ tBTA_GATTS_INT_START_IF *p_buf;
+ tBTA_GATTS cb_data;
+ tBTA_GATT_STATUS status = BTA_GATT_OK;
+ UINT8 i, first_unuse = 0xff;
+
+ if (!p_cb->enabled)
+ bta_gatts_enable(p_cb);
+
+
+ for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+ {
+ if (p_cb->rcb[i].in_use)
+ {
+ if (bta_gatts_uuid_compare(p_cb->rcb[i].app_uuid, p_msg->api_reg.app_uuid))
+ {
+ APPL_TRACE_ERROR0("application already registered.");
+ status = BTA_GATT_DUP_REG;
+ break;
+ }
+ }
+ }
+
+ if (status == BTA_GATT_OK)
+ {
+ for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+ {
+ if (first_unuse == 0xff && !p_cb->rcb[i].in_use)
+ {
+ first_unuse = i;
+ break;
+ }
+ }
+
+ cb_data.reg_oper.server_if = BTA_GATTS_INVALID_IF;
+// btla-specific ++
+ memcpy(&cb_data.reg_oper.uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
+// btla-specific --
+ if (first_unuse != 0xff)
+ {
+ APPL_TRACE_ERROR1("register application first_unuse rcb_idx = %d", first_unuse);
+
+ p_cb->rcb[first_unuse].in_use = TRUE;
+ p_cb->rcb[first_unuse].p_cback = p_msg->api_reg.p_cback;
+ memcpy(&p_cb->rcb[first_unuse].app_uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
+ cb_data.reg_oper.server_if =
+ p_cb->rcb[first_unuse].gatt_if = GATT_Register(&p_msg->api_reg.app_uuid, &bta_gatts_cback);
+ if ( !p_cb->rcb[first_unuse].gatt_if)
+ {
+ status = BTA_GATT_NO_RESOURCES;
+ }
+ else
+ {
+ if ((p_buf = (tBTA_GATTS_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTS_INT_START_IF))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTS_INT_START_IF_EVT;
+ p_buf->server_if = p_cb->rcb[first_unuse].gatt_if;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ else
+ {
+ status = BTA_GATT_NO_RESOURCES;
+ memset( &p_cb->rcb[first_unuse], 0 , sizeof(tBTA_GATTS_RCB));
+ }
+ }
+ }
+ else
+ {
+ status = BTA_GATT_NO_RESOURCES;
+ }
+
+ }
+ cb_data.reg_oper.status = status;
+ if (p_msg->api_reg.p_cback)
+ (*p_msg->api_reg.p_cback)(BTA_GATTS_REG_EVT, &cb_data);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gatts_start_if
+**
+** Description start an application interface.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_start_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+ if (bta_gatts_find_app_rcb_by_app_if(p_msg->int_start_if.server_if))
+ {
+ GATT_StartIf(p_msg->int_start_if.server_if);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.server_if );
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gatts_deregister
+**
+** Description deregister an application.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+ tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+ tBTA_GATTS_CBACK *p_cback = NULL;
+ UINT8 i;
+ tBTA_GATTS cb_data;
+
+ cb_data.reg_oper.server_if = p_msg->api_dereg.server_if;
+ cb_data.reg_oper.status = status;
+
+ for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+ {
+ if (p_cb->rcb[i].in_use && p_cb->rcb[i].gatt_if == p_msg->api_dereg.server_if)
+ {
+ p_cback = p_cb->rcb[i].p_cback;
+ status = BTA_GATT_OK;
+
+ /* deregister the app */
+ GATT_Deregister(p_cb->rcb[i].gatt_if);
+
+ /* reset cb */
+ memset(&p_cb->rcb[i], 0, sizeof(tBTA_GATTS_RCB));
+ cb_data.reg_oper.status = status;
+ break;
+ }
+ }
+
+ if (p_cback)
+ {
+ (*p_cback)(BTA_GATTS_DEREG_EVT, &cb_data);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("application not registered.");
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gatts_create_srvc
+**
+** Description action function to create a service.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+ UINT8 rcb_idx;
+ tBTA_GATTS cb_data;
+ UINT8 srvc_idx;
+ UINT16 service_id = 0;
+ //tBTA_GATTS_HNDL_RANGE handle_range;
+
+ cb_data.create.status = BTA_GATT_ERROR;
+
+ rcb_idx = bta_gatts_find_app_rcb_idx_by_app_if(p_cb, p_msg->api_create_svc.server_if);
+
+ APPL_TRACE_ERROR1("create service rcb_idx = %d", rcb_idx);
+
+ if (rcb_idx != BTA_GATTS_INVALID_APP)
+ {
+ if ((srvc_idx = bta_gatts_alloc_srvc_cb(p_cb, rcb_idx)) != BTA_GATTS_INVALID_APP)
+ {
+ /* create the service now */
+ service_id = GATTS_CreateService (p_cb->rcb[rcb_idx].gatt_if,
+ &p_msg->api_create_svc.service_uuid,
+ p_msg->api_create_svc.inst,
+ p_msg->api_create_svc.num_handle,
+ p_msg->api_create_svc.is_pri);
+
+ if (service_id != 0)
+ {
+ memcpy(&p_cb->srvc_cb[srvc_idx].service_uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
+ p_cb->srvc_cb[srvc_idx].service_id = service_id;
+ p_cb->srvc_cb[srvc_idx].inst_num = p_msg->api_create_svc.inst;
+ p_cb->srvc_cb[srvc_idx].idx = srvc_idx;
+
+ cb_data.create.status = BTA_GATT_OK;
+ cb_data.create.service_id = service_id;
+// btla-specific ++
+ cb_data.create.is_primary = p_msg->api_create_svc.is_pri;
+// btla-specific --
+ cb_data.create.server_if = p_cb->rcb[rcb_idx].gatt_if;
+ }
+ else
+ {
+ cb_data.status = BTA_GATT_ERROR;
+ memset(&p_cb->srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
+ APPL_TRACE_ERROR0("service creation failed.");
+ }
+// btla-specific ++
+ memcpy(&cb_data.create.uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
+ cb_data.create.svc_instance= p_msg->api_create_svc.inst;
+// btla-specific --
+ }
+ if (p_cb->rcb[rcb_idx].p_cback)
+ (* p_cb->rcb[rcb_idx].p_cback)(BTA_GATTS_CREATE_EVT, &cb_data);
+ }
+ else /* application not registered */
+ {
+ APPL_TRACE_ERROR0("Application not registered");
+ }
+}
+/*******************************************************************************
+**
+** Function bta_gatts_add_include_srvc
+**
+** Description action function to add an included service.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb,tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+ UINT16 attr_id = 0;
+ tBTA_GATTS cb_data;
+
+ attr_id = GATTS_AddIncludeService(p_msg->api_add_incl_srvc.hdr.layer_specific,
+ p_msg->api_add_incl_srvc.included_service_id);
+
+ cb_data.add_result.server_if = p_rcb->gatt_if;
+ cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+ cb_data.add_result.attr_id = attr_id;
+
+ if (attr_id)
+ {
+ cb_data.add_result.status = BTA_GATT_OK;
+ }
+ else
+ {
+ cb_data.add_result.status = BTA_GATT_ERROR;
+ }
+
+ if (p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_ADD_INCL_SRVC_EVT, &cb_data);
+}
+/*******************************************************************************
+**
+** Function bta_gatts_add_char
+**
+** Description action function to add characteristic.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+ UINT16 attr_id = 0;
+ tBTA_GATTS cb_data;
+
+ attr_id = GATTS_AddCharacteristic(p_msg->api_add_char.hdr.layer_specific,
+ &p_msg->api_add_char.char_uuid,
+ p_msg->api_add_char.perm,
+ p_msg->api_add_char.property);
+ cb_data.add_result.server_if = p_rcb->gatt_if;
+ cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+ cb_data.add_result.attr_id = attr_id;
+// btla-specific ++
+ memcpy(&cb_data.add_result.char_uuid, &p_msg->api_add_char.char_uuid, sizeof(tBT_UUID));
+// btla-specific --
+
+ if (attr_id)
+ {
+ cb_data.add_result.status = BTA_GATT_OK;
+ }
+ else
+ {
+ cb_data.add_result.status = BTA_GATT_ERROR;
+ }
+
+ if (p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_EVT, &cb_data);
+}
+/*******************************************************************************
+**
+** Function bta_gatts_add_char_descr
+**
+** Description action function to add characteristic descriptor.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+ UINT16 attr_id = 0;
+ tBTA_GATTS cb_data;
+
+ attr_id = GATTS_AddCharDescriptor(p_msg->api_add_char_descr.hdr.layer_specific,
+ p_msg->api_add_char_descr.perm,
+ &p_msg->api_add_char_descr.descr_uuid);
+
+ cb_data.add_result.server_if = p_rcb->gatt_if;
+ cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+ cb_data.add_result.attr_id = attr_id;
+// btla-specific ++
+ memcpy(&cb_data.add_result.char_uuid, &p_msg->api_add_char_descr.descr_uuid, sizeof(tBT_UUID));
+// btla-specific --
+
+ if (attr_id)
+ {
+ cb_data.add_result.status = BTA_GATT_OK;
+ }
+ else
+ {
+ cb_data.add_result.status = BTA_GATT_ERROR;
+ }
+
+ if (p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_DESCR_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function bta_gatts_delete_service
+**
+** Description action function to delete a service.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+ tBTA_GATTS cb_data;
+
+ cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+ cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+
+ if (GATTS_DeleteService(p_rcb->gatt_if,
+ &p_srvc_cb->service_uuid,
+ p_srvc_cb->inst_num))
+ {
+ cb_data.srvc_oper.status = BTA_GATT_OK;
+ memset(p_srvc_cb, 0, sizeof(tBTA_GATTS_SRVC_CB));
+ }
+ else
+ {
+ cb_data.srvc_oper.status = BTA_GATT_ERROR;
+ }
+
+ if (p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_DELELTE_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function bta_gatts_start_service
+**
+** Description action function to start a service.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+ tBTA_GATTS cb_data;
+
+ cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+ cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+
+ if (GATTS_StartService(p_rcb->gatt_if,
+ p_srvc_cb->service_id,
+ p_msg->api_start.transport) == GATT_SUCCESS)
+ {
+ APPL_TRACE_DEBUG1("bta_gatts_start_service service_id= %d", p_srvc_cb->service_id);
+ cb_data.srvc_oper.status = BTA_GATT_OK;
+ }
+ else
+ {
+ cb_data.srvc_oper.status = BTA_GATT_ERROR;
+ }
+
+ if (p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_START_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function bta_gatts_stop_service
+**
+** Description action function to stop a service.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+ tBTA_GATTS cb_data;
+
+ GATTS_StopService(p_srvc_cb->service_id);
+ cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+ cb_data.srvc_oper.service_id = p_srvc_cb->service_id;
+ cb_data.srvc_oper.status = BTA_GATT_OK;
+ APPL_TRACE_ERROR1("bta_gatts_stop_service service_id= %d", p_srvc_cb->service_id);
+
+ if (p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_STOP_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function bta_gatts_send_rsp
+**
+** Description GATTS send response.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_send_rsp (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+
+ if (GATTS_SendRsp (p_msg->api_rsp.hdr.layer_specific,
+ p_msg->api_rsp.trans_id,
+ p_msg->api_rsp.status,
+ (tGATTS_RSP *)p_msg->api_rsp.p_rsp) != GATT_SUCCESS)
+ {
+ APPL_TRACE_ERROR0("Sending response failed");
+ }
+
+}
+/*******************************************************************************
+**
+** Function bta_gatts_send_rsp
+**
+** Description GATTS send response.
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_SRVC_CB *p_srvc_cb;
+ tBTA_GATT_STATUS status;
+
+
+ p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id (p_cb, p_msg->api_indicate.attr_id);
+
+ if (p_srvc_cb )
+ {
+ if (p_msg->api_indicate.need_confirm)
+
+ status = GATTS_HandleValueIndication (p_msg->api_indicate.hdr.layer_specific,
+ p_msg->api_indicate.attr_id,
+ p_msg->api_indicate.len,
+ p_msg->api_indicate.value);
+ else
+ status = GATTS_HandleValueNotification (p_msg->api_indicate.hdr.layer_specific,
+ p_msg->api_indicate.attr_id,
+ p_msg->api_indicate.len,
+ p_msg->api_indicate.value);
+
+ if (status != GATT_SUCCESS &&
+ p_msg->api_indicate.need_confirm &&
+ p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)
+ {
+ (*p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)(BTA_GATTS_CONF_EVT, (tBTA_GATTS *)&status);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Not an registered servce attribute ID: 0x%04x", p_msg->api_indicate.attr_id);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gatts_open
+**
+** Description
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb=NULL;
+ tBTA_GATT_STATUS status= BTA_GATT_ERROR;
+
+
+ if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_open.server_if)) != NULL)
+ {
+ if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda, p_msg->api_open.is_direct))
+ {
+ status = BTA_GATT_OK;
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Inavlide server_if=%d", p_msg->api_open.server_if);
+ }
+
+ if (p_rcb && p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_OPEN_EVT, (tBTA_GATTS *)&status);
+
+}
+/*******************************************************************************
+**
+** Function bta_gatts_cancel_open
+**
+** Description
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb;
+ tBTA_GATT_STATUS status= BTA_GATT_ERROR;
+
+ if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_cancel_open.server_if)) != NULL)
+ {
+ if (!GATT_CancelConnect(p_rcb->gatt_if, p_msg->api_cancel_open.remote_bda, p_msg->api_cancel_open.is_direct))
+ {
+ APPL_TRACE_ERROR0("bta_gatts_cancel_open failed for open request");
+ }
+ else
+ {
+ status= BTA_GATT_OK;
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Inavlide server_if=%d", p_msg->api_cancel_open.server_if);
+ }
+
+ if (p_rcb && p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_CANCEL_OPEN_EVT, (tBTA_GATTS *)&status);
+}
+/*******************************************************************************
+**
+** Function bta_gatts_close
+**
+** Description
+**
+** Returns none.
+**
+*******************************************************************************/
+void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+ tBTA_GATTS_RCB *p_rcb;
+ tBTA_GATT_STATUS status= BTA_GATT_ERROR;
+ tGATT_IF gatt_if;
+ BD_ADDR remote_bda;
+
+ if (GATT_GetConnectionInfor(p_msg->hdr.layer_specific, &gatt_if, remote_bda))
+ {
+ if (GATT_Disconnect(p_msg->hdr.layer_specific) != GATT_SUCCESS)
+ {
+ APPL_TRACE_ERROR1("bta_gatts_close fail conn_id=%d", p_msg->hdr.layer_specific);
+ }
+ else
+ {
+ status= BTA_GATT_OK;
+ }
+
+ p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+ if (p_rcb && p_rcb->p_cback)
+ (*p_rcb->p_cback)(BTA_GATTS_CLOSE_EVT, (tBTA_GATTS *)&status);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Unknown connection ID: %d", p_msg->hdr.layer_specific);
+ }
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_gatts_request_cback
+**
+** Description GATTS attribute request callback.
+**
+** Returns none.
+**
+*******************************************************************************/
+static void bta_gatts_send_request_cback (UINT16 conn_id,
+ UINT32 trans_id,
+ tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data)
+{
+ tBTA_GATTS cb_data;
+ tBTA_GATTS_RCB *p_rcb;
+ tGATT_IF gatt_if;
+
+ memset(&cb_data, 0 , sizeof(tBTA_GATTS));
+
+ if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda))
+ {
+ p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+ APPL_TRACE_DEBUG3 ("bta_gatts_send_request_cback conn_id=%d trans_id=%d req_type=%d", conn_id, trans_id, req_type);
+
+ if (p_rcb && p_rcb->p_cback)
+ {
+ cb_data.req_data.conn_id = conn_id;
+ cb_data.req_data.trans_id = trans_id;
+ cb_data.req_data.p_data = (tBTA_GATTS_REQ_DATA *)p_data;
+
+ (*p_rcb->p_cback)(req_type, &cb_data);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("connection request on gatt_if[%d] is not interested", gatt_if);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("request received on unknown connectino ID: %d", conn_id);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_gatts_conn_cback
+**
+** Description connection callback.
+**
+** Returns none.
+**
+*******************************************************************************/
+static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+ BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+ tBTA_GATTS cb_data;
+ UINT8 evt = connected ? BTA_GATTS_CONNECT_EVT: BTA_GATTS_DISCONNECT_EVT;
+ tBTA_GATTS_RCB *p_reg;
+
+ APPL_TRACE_DEBUG4 ("bta_gatts_conn_cback gatt_if=%d conn_id=%d connected=%d reason = 0x%04d",
+ gatt_if, conn_id, connected, reason);
+ APPL_TRACE_DEBUG6("bta_gatts_conn_cback bda :%02x-%02x-%02x-%02x-%02x-%02x ",
+ bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+
+ p_reg = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+ if (p_reg && p_reg->p_cback)
+ {
+ cb_data.conn.conn_id = conn_id;
+ cb_data.conn.server_if = gatt_if;
+ cb_data.conn.reason = reason;
+ memcpy(cb_data.conn.remote_bda, bda, BD_ADDR_LEN);
+ (*p_reg->p_cback)(evt, &cb_data);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_gatts_conn_cback server_if=%d not found",gatt_if);
+ }
+}
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_api.c b/bta/gatt/bta_gatts_api.c
new file mode 100644
index 0000000..65df0a6
--- /dev/null
+++ b/bta/gatt/bta_gatts_api.c
@@ -0,0 +1,512 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation of the API for GATT server of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gatts_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_gatts_reg =
+{
+ bta_gatts_hdl_event,
+ NULL /* need a disable functino to be called when BT is disabled */
+};
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_AppRegister
+**
+** Description This function is called to register application callbacks
+** with BTA GATTS module.
+**
+** Parameters p_app_uuid - applicaiton UUID
+** p_cback - pointer to the application callback function.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTS_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTS_CBACK *p_cback)
+{
+ tBTA_GATTS_API_REG *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ if (!bta_gatts_cb.enabled)
+ {
+ bta_sys_register(BTA_ID_GATTS, &bta_gatts_reg);
+ }
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_GATTS_API_REG *) GKI_getbuf(sizeof(tBTA_GATTS_API_REG))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTS_API_REG_EVT;
+
+ if (p_app_uuid != NULL)
+ memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
+ p_buf->p_cback = p_cback;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_AppDeregister
+**
+** Description De-register with GATT Server.
+**
+** Parameters app_id: applicatino ID.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if)
+{
+ tBTA_GATTS_API_DEREG *p_buf;
+
+ if ((p_buf = (tBTA_GATTS_API_DEREG *) GKI_getbuf(sizeof(tBTA_GATTS_API_DEREG))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTS_API_DEREG_EVT;
+ p_buf->server_if = server_if;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_CreateService
+**
+** Description Create a service. When service creation is done, a callback
+** event BTA_GATTS_CREATE_SRVC_EVT is called to report status
+** and service ID to the profile. The service ID obtained in
+** the callback function needs to be used when adding included
+** service and characteristics/descriptors into the service.
+**
+** Parameters app_id: Profile ID this service is belonged to.
+** p_service_uuid: service UUID.
+** inst: instance ID number of this service.
+** num_handle: numble of handle requessted for this service.
+** is_primary: is this service a primary one or not.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, tBT_UUID *p_service_uuid, UINT8 inst,
+ UINT16 num_handle, BOOLEAN is_primary)
+{
+ tBTA_GATTS_API_CREATE_SRVC *p_buf;
+
+ if ((p_buf = (tBTA_GATTS_API_CREATE_SRVC *) GKI_getbuf(sizeof(tBTA_GATTS_API_CREATE_SRVC))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTS_API_CREATE_SRVC_EVT;
+
+ p_buf->server_if = server_if;
+ p_buf->inst = inst;
+ memcpy(&p_buf->service_uuid, p_service_uuid, sizeof(tBT_UUID));
+ p_buf->num_handle = num_handle;
+ p_buf->is_pri = is_primary;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+/*******************************************************************************
+**
+** Function BTA_GATTS_AddIncludeService
+**
+** Description This function is called to add an included service. After included
+** service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
+** is reported the included service ID.
+**
+** Parameters service_id: service ID to which this included service is to
+** be added.
+** included_service_id: the service ID to be included.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id)
+{
+ tBTA_GATTS_API_ADD_INCL_SRVC *p_buf;
+
+ if ((p_buf =
+ (tBTA_GATTS_API_ADD_INCL_SRVC *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_INCL_SRVC)))
+ != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTS_API_ADD_INCL_SRVC_EVT;
+
+ p_buf->hdr.layer_specific = service_id;
+ p_buf->included_service_id = included_service_id;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTS_AddCharacteristic
+**
+** Description This function is called to add a characteristic into a service.
+**
+** Parameters service_id: service ID to which this included service is to
+** be added.
+** p_char_uuid : Characteristic UUID.
+** perm : Characteristic value declaration attribute permission.
+** property : Characteristic Properties
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
+ tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property)
+{
+ tBTA_GATTS_API_ADD_CHAR *p_buf;
+
+ if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR));
+
+ p_buf->hdr.event = BTA_GATTS_API_ADD_CHAR_EVT;
+ p_buf->hdr.layer_specific = service_id;
+ p_buf->perm = perm;
+ p_buf->property = property;
+
+ if (p_char_uuid)
+ {
+ memcpy(&p_buf->char_uuid, p_char_uuid, sizeof(tBT_UUID));
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_AddCharDescriptor
+**
+** Description This function is called to add characteristic descriptor. When
+** it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
+** to report the status and an ID number for this descriptor.
+**
+** Parameters service_id: service ID to which this charatceristic descriptor is to
+** be added.
+** perm: descriptor access permission.
+** p_descr_uuid: descriptor UUID.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
+ tBTA_GATT_PERM perm,
+ tBT_UUID * p_descr_uuid)
+{
+ tBTA_GATTS_API_ADD_DESCR *p_buf;
+ UINT16 len = sizeof(tBTA_GATTS_API_ADD_DESCR);
+
+
+ if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_buf, 0, len);
+
+ p_buf->hdr.event = BTA_GATTS_API_ADD_DESCR_EVT;
+ p_buf->hdr.layer_specific = service_id;
+ p_buf->perm = perm;
+
+ if (p_descr_uuid)
+ {
+ memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID));
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_DeleteService
+**
+** Description This function is called to delete a service. When this is done,
+** a callback event BTA_GATTS_DELETE_EVT is report with the status.
+**
+** Parameters service_id: service_id to be deleted.
+**
+** Returns returns none.
+**
+*******************************************************************************/
+void BTA_GATTS_DeleteService(UINT16 service_id)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_GATTS_API_DEL_SRVC_EVT;
+
+ p_buf->layer_specific = service_id;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_StartService
+**
+** Description This function is called to start a service.
+**
+** Parameters service_id: the service ID to be started.
+** sup_transport: supported trasnport.
+**
+** Returns None.
+**
+*******************************************************************************/
+void BTA_GATTS_StartService(UINT16 service_id, tBTA_GATT_TRANSPORT sup_transport)
+{
+ tBTA_GATTS_API_START *p_buf;
+
+ if ((p_buf = (tBTA_GATTS_API_START *) GKI_getbuf(sizeof(tBTA_GATTS_API_START))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTS_API_START_SRVC_EVT;
+
+ p_buf->hdr.layer_specific = service_id;
+ p_buf->transport = sup_transport;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_StopService
+**
+** Description This function is called to stop a service.
+**
+** Parameters service_id - service to be topped.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTS_StopService(UINT16 service_id)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_GATTS_API_STOP_SRVC_EVT;
+
+ p_buf->layer_specific = service_id;
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_HandleValueIndication
+**
+** Description This function is called to read a characteristics descriptor.
+**
+** Parameters bda - remote device bd address to indicate.
+** attr_id - attribute ID to indicate.
+** data_len - indicate data length.
+** p_data: data to indicate.
+** need_confirm - if this indication expects a confirmation or not.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id, UINT16 data_len,
+ UINT8 *p_data, BOOLEAN need_confirm)
+{
+ tBTA_GATTS_API_INDICATION *p_buf;
+ UINT16 len = sizeof(tBTA_GATTS_API_INDICATION);
+
+ if ((p_buf = (tBTA_GATTS_API_INDICATION *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_buf, 0, len);
+
+ p_buf->hdr.event = BTA_GATTS_API_INDICATION_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->attr_id = attr_id;
+ p_buf->need_confirm = need_confirm;
+
+ if (data_len > 0 && p_data != NULL)
+ {
+ p_buf->len = data_len;
+ memcpy(p_buf->value, p_data, data_len);
+
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+/*******************************************************************************
+**
+** Function BTA_GATTS_SendRsp
+**
+** Description This function is called to send a response to a request.
+**
+** Parameters conn_id - connection identifier.
+** trans_id - transaction ID.
+** status - response status
+** p_msg - response data.
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
+ tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg)
+{
+ tBTA_GATTS_API_RSP *p_buf;
+ UINT16 len = sizeof(tBTA_GATTS_API_RSP) + sizeof(tBTA_GATTS_RSP);
+
+ if ((p_buf = (tBTA_GATTS_API_RSP *) GKI_getbuf(len)) != NULL)
+ {
+ memset(p_buf, 0, len);
+
+ p_buf->hdr.event = BTA_GATTS_API_RSP_EVT;
+ p_buf->hdr.layer_specific = conn_id;
+ p_buf->trans_id = trans_id;
+ p_buf->status = status;
+
+ if (p_msg != NULL)
+ {
+ p_buf->p_rsp = (tBTA_GATTS_RSP *)(p_buf + 1);
+ memcpy(p_buf->p_rsp, p_msg, sizeof(tBTA_GATTS_RSP));
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_Open
+**
+** Description Open a direct open connection or add a background auto connection
+** bd address
+**
+** Parameters server_if: server interface.
+** remote_bda: remote device BD address.
+** is_direct: direct connection or background auto connection
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+ tBTA_GATTS_API_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_GATTS_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTS_API_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTS_API_OPEN_EVT;
+ p_buf->server_if = server_if;
+ p_buf->is_direct = is_direct;
+ memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_CancelOpen
+**
+** Description Cancel a direct open connection or remove a background auto connection
+** bd address
+**
+** Parameters server_if: server interface.
+** remote_bda: remote device BD address.
+** is_direct: direct connection or background auto connection
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+ tBTA_GATTS_API_CANCEL_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_GATTS_API_CANCEL_OPEN *) GKI_getbuf(sizeof(tBTA_GATTS_API_CANCEL_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_GATTS_API_CANCEL_OPEN_EVT;
+ p_buf->server_if = server_if;
+ p_buf->is_direct = is_direct;
+ memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_Close
+**
+** Description Close a connection a remote device.
+**
+** Parameters conn_id: connectino ID to be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_GATTS_Close(UINT16 conn_id)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_GATTS_API_CLOSE_EVT;
+ p_buf->layer_specific = conn_id;
+ bta_sys_sendmsg(p_buf);
+ }
+ return;
+
+}
+
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_int.h b/bta/gatt/bta_gatts_int.h
new file mode 100644
index 0000000..4810c05
--- /dev/null
+++ b/bta/gatt/bta_gatts_int.h
@@ -0,0 +1,246 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private file for the BTA GATT server.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTS_INT_H
+#define BTA_GATTS_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "gatt_api.h"
+//#include "bta_gatts_co.h"
+
+#include "gki.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+enum
+{
+ BTA_GATTS_API_REG_EVT = BTA_SYS_EVT_START(BTA_ID_GATTS),
+ BTA_GATTS_INT_START_IF_EVT,
+ BTA_GATTS_API_DEREG_EVT,
+ BTA_GATTS_API_CREATE_SRVC_EVT,
+ BTA_GATTS_API_INDICATION_EVT,
+
+ BTA_GATTS_API_ADD_INCL_SRVC_EVT,
+ BTA_GATTS_API_ADD_CHAR_EVT,
+ BTA_GATTS_API_ADD_DESCR_EVT,
+ BTA_GATTS_API_DEL_SRVC_EVT,
+ BTA_GATTS_API_START_SRVC_EVT,
+ BTA_GATTS_API_STOP_SRVC_EVT,
+ BTA_GATTS_API_RSP_EVT,
+ BTA_GATTS_API_OPEN_EVT,
+ BTA_GATTS_API_CANCEL_OPEN_EVT,
+ BTA_GATTS_API_CLOSE_EVT
+
+};
+typedef UINT16 tBTA_GATTS_INT_EVT;
+
+/* max number of application allowed on device */
+#define BTA_GATTS_MAX_APP_NUM GATT_MAX_SR_PROFILES
+
+/* max number of services allowed in the device */
+#define BTA_GATTS_MAX_SRVC_NUM GATT_MAX_SR_PROFILES
+
+/* internal strucutre for GATTC register API */
+typedef struct
+{
+ BT_HDR hdr;
+ tBT_UUID app_uuid;
+ tBTA_GATTS_CBACK *p_cback;
+}tBTA_GATTS_API_REG;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATTS_IF server_if;
+}tBTA_GATTS_INT_START_IF;
+
+typedef tBTA_GATTS_INT_START_IF tBTA_GATTS_API_DEREG;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATTS_IF server_if;
+ tBT_UUID service_uuid;
+ UINT16 num_handle;
+ UINT8 inst;
+ BOOLEAN is_pri;
+
+} tBTA_GATTS_API_CREATE_SRVC;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBT_UUID char_uuid;
+ tBTA_GATT_PERM perm;
+ tBTA_GATT_CHAR_PROP property;
+
+}tBTA_GATTS_API_ADD_CHAR;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 included_service_id;
+
+}tBTA_GATTS_API_ADD_INCL_SRVC;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBT_UUID descr_uuid;
+ tBTA_GATT_PERM perm;
+}tBTA_GATTS_API_ADD_DESCR;
+
+typedef struct
+{
+ BT_HDR hdr;
+ //todo BD_ADDR bd_addr;
+ UINT16 attr_id;
+ UINT16 len;
+ BOOLEAN need_confirm;
+ UINT8 value[BTA_GATT_MAX_ATTR_LEN];
+}tBTA_GATTS_API_INDICATION;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT32 trans_id;
+ tBTA_GATT_STATUS status;
+ tBTA_GATTS_RSP *p_rsp;
+}tBTA_GATTS_API_RSP;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATT_TRANSPORT transport;
+}tBTA_GATTS_API_START;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR remote_bda;
+ tBTA_GATTS_IF server_if;
+ BOOLEAN is_direct;
+}tBTA_GATTS_API_OPEN;
+
+typedef tBTA_GATTS_API_OPEN tBTA_GATTS_API_CANCEL_OPEN;
+
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_GATTS_API_REG api_reg;
+ tBTA_GATTS_API_DEREG api_dereg;
+ tBTA_GATTS_API_CREATE_SRVC api_create_svc;
+ tBTA_GATTS_API_ADD_INCL_SRVC api_add_incl_srvc;
+ tBTA_GATTS_API_ADD_CHAR api_add_char;
+ tBTA_GATTS_API_ADD_DESCR api_add_char_descr;
+ tBTA_GATTS_API_START api_start;
+ tBTA_GATTS_API_INDICATION api_indicate;
+ tBTA_GATTS_API_RSP api_rsp;
+ tBTA_GATTS_API_OPEN api_open;
+ tBTA_GATTS_API_CANCEL_OPEN api_cancel_open;
+
+ tBTA_GATTS_INT_START_IF int_start_if;
+} tBTA_GATTS_DATA;
+
+/* application registration control block */
+typedef struct
+{
+ BOOLEAN in_use;
+ tBT_UUID app_uuid;
+ tBTA_GATTS_CBACK *p_cback;
+ tBTA_GATTS_IF gatt_if; //todo cahneg to server_if
+}tBTA_GATTS_RCB;
+
+/* service registration control block */
+typedef struct
+{
+ tBT_UUID service_uuid; /* service UUID */
+ UINT16 service_id; /* service handle */
+ UINT8 inst_num; /* instance ID */
+ UINT8 rcb_idx;
+ UINT8 idx; /* self index of serviec CB */
+ BOOLEAN in_use;
+
+}tBTA_GATTS_SRVC_CB;
+
+
+/* GATT server control block */
+typedef struct
+{
+ BOOLEAN enabled;
+ tBTA_GATTS_RCB rcb[BTA_GATTS_MAX_APP_NUM];
+ tBTA_GATTS_SRVC_CB srvc_cb[BTA_GATTS_MAX_SRVC_NUM];
+}tBTA_GATTS_CB;
+
+
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTS_CB bta_gatts_cb;
+#else
+extern tBTA_GATTS_CB *bta_gatts_cb_ptr;
+ #define bta_gatts_cb (*bta_gatts_cb_ptr)
+#endif
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg);
+
+extern void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_start_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+
+extern void bta_gatts_send_rsp(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+
+
+extern void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+
+extern BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src);
+extern tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if);
+extern UINT8 bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_IF server_if);
+extern UINT8 bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB *p_cb, UINT8 rcb_idx);
+extern tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB *p_cb, UINT16 service_id);
+extern tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_cb, UINT16 attr_id);
+
+
+#endif /* BTA_GATTS_INT_H */
+
diff --git a/bta/gatt/bta_gatts_main.c b/bta/gatt/bta_gatts_main.c
new file mode 100644
index 0000000..e2b2494
--- /dev/null
+++ b/bta/gatt/bta_gatts_main.c
@@ -0,0 +1,134 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the GATT server main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_gatts_int.h"
+#include "gki.h"
+
+/* type for service building action functions */
+typedef void (*tBTA_GATTS_SRVC_ACT)(tBTA_GATTS_SRVC_CB *p_rcb, tBTA_GATTS_DATA *p_data);
+
+/* service building action function list */
+const tBTA_GATTS_SRVC_ACT bta_gatts_srvc_build_act[] =
+{
+ bta_gatts_add_include_srvc,
+ bta_gatts_add_char,
+ bta_gatts_add_char_descr,
+ bta_gatts_delete_service,
+ bta_gatts_start_service,
+ bta_gatts_stop_service,
+};
+
+/* GATTS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_GATTS_CB bta_gatts_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function bta_gatts_hdl_event
+**
+** Description BTA GATT server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg)
+{
+ tBTA_GATTS_CB *p_cb = &bta_gatts_cb;
+ tBTA_GATTS_SRVC_CB *p_srvc_cb = NULL;
+
+ switch (p_msg->event)
+ {
+ case BTA_GATTS_API_REG_EVT:
+ bta_gatts_register(p_cb, (tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_INT_START_IF_EVT:
+ bta_gatts_start_if(p_cb, (tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_API_DEREG_EVT:
+ bta_gatts_deregister(p_cb, (tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_API_CREATE_SRVC_EVT:
+ bta_gatts_create_srvc(p_cb, (tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_API_INDICATION_EVT:
+ bta_gatts_indicate_handle(p_cb,(tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_API_OPEN_EVT:
+ bta_gatts_open(p_cb,(tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_API_CANCEL_OPEN_EVT:
+ bta_gatts_cancel_open(p_cb,(tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_API_CLOSE_EVT:
+ bta_gatts_close(p_cb,(tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_API_RSP_EVT:
+ bta_gatts_send_rsp(p_cb,(tBTA_GATTS_DATA *) p_msg);
+ break;
+
+ case BTA_GATTS_API_ADD_INCL_SRVC_EVT:
+ case BTA_GATTS_API_ADD_CHAR_EVT:
+ case BTA_GATTS_API_ADD_DESCR_EVT:
+ case BTA_GATTS_API_DEL_SRVC_EVT:
+ case BTA_GATTS_API_START_SRVC_EVT:
+ case BTA_GATTS_API_STOP_SRVC_EVT:
+
+ p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
+ ((tBTA_GATTS_DATA *)p_msg)->api_add_incl_srvc.hdr.layer_specific);
+
+ if (p_srvc_cb != NULL)
+ {
+ bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("service not created");
+ }
+ break;
+
+ default:
+ break;
+ }
+
+
+ return (TRUE);
+}
+
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_utils.c b/bta/gatt/bta_gatts_utils.c
new file mode 100644
index 0000000..5145c95
--- /dev/null
+++ b/bta/gatt/bta_gatts_utils.c
@@ -0,0 +1,235 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the GATT client utility function.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatts_int.h"
+#include "bd.h"
+
+static const UINT8 base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/*******************************************************************************
+**
+** Function bta_gatt_convert_uuid16_to_uuid128
+**
+** Description Convert a 16 bits UUID to be an standard 128 bits one.
+**
+** Returns TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+static void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
+{
+ UINT8 *p = &uuid_128[LEN_UUID_128 - 4];
+
+ memcpy (uuid_128, base_uuid, LEN_UUID_128);
+
+ UINT16_TO_STREAM(p, uuid_16);
+}
+/*******************************************************************************
+**
+** Function bta_gatts_alloc_srvc_cb
+**
+** Description allocate a service control block.
+**
+** Returns pointer to the control block, or otherwise NULL when failed.
+**
+*******************************************************************************/
+UINT8 bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB *p_cb, UINT8 rcb_idx)
+{
+ UINT8 i;
+
+ for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++)
+ {
+ if (!p_cb->srvc_cb[i].in_use)
+ {
+ p_cb->srvc_cb[i].in_use = TRUE;
+ p_cb->srvc_cb[i].rcb_idx = rcb_idx;
+ return i;
+ }
+ }
+ return BTA_GATTS_INVALID_APP;
+}
+
+/*******************************************************************************
+**
+** Function bta_gatts_find_app_rcb_by_app_if
+**
+** Description find the index of the application control block by app ID.
+**
+** Returns pointer to the control block if success, otherwise NULL
+**
+*******************************************************************************/
+tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if)
+{
+ UINT8 i;
+ tBTA_GATTS_RCB *p_reg;
+
+ for (i = 0, p_reg = bta_gatts_cb.rcb; i < BTA_GATTS_MAX_APP_NUM; i ++, p_reg++)
+ {
+ if (p_reg->in_use && p_reg->gatt_if == server_if)
+ return p_reg;
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_gatts_find_app_rcb_idx_by_app_if
+**
+** Description find the index of the application control block by app ID.
+**
+** Returns index of the control block, or BTA_GATTS_INVALID_APP if failed.
+**
+*******************************************************************************/
+
+UINT8 bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_IF server_if)
+{
+ UINT8 i;
+
+ for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+ {
+ if (p_cb->rcb[i].in_use && p_cb->rcb[i].gatt_if == server_if)
+ return i;
+ }
+ return BTA_GATTS_INVALID_APP;
+}
+/*******************************************************************************
+**
+** Function bta_gatts_find_srvc_cb_by_srvc_id
+**
+** Description find the service control block by service ID.
+**
+** Returns pointer to the rcb.
+**
+*******************************************************************************/
+tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB *p_cb, UINT16 service_id)
+{
+ UINT8 i;
+ APPL_TRACE_DEBUG1("bta_gatts_find_srvc_cb_by_srvc_id service_id=%d", service_id);
+ for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++)
+ {
+ if (p_cb->srvc_cb[i].in_use &&
+ p_cb->srvc_cb[i].service_id == service_id)
+ {
+ APPL_TRACE_DEBUG1("bta_gatts_find_srvc_cb_by_srvc_id found service cb index =%d", i);
+ return &p_cb->srvc_cb[i];
+ }
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function bta_gatts_find_srvc_cb_by_attr_id
+**
+** Description find the service control block by attribute ID.
+**
+** Returns pointer to the rcb.
+**
+*******************************************************************************/
+tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_cb, UINT16 attr_id)
+{
+ UINT8 i;
+
+ for (i = 0; i < (BTA_GATTS_MAX_SRVC_NUM); i ++)
+ {
+ if (/* middle service */
+ (i < (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+ p_cb->srvc_cb[i].in_use &&
+ p_cb->srvc_cb[i + 1].in_use &&
+ attr_id >= p_cb->srvc_cb[i].service_id &&
+ attr_id < p_cb->srvc_cb[i + 1].service_id) ||
+ /* last active service */
+ (i < (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+ p_cb->srvc_cb[i].in_use &&
+ !p_cb->srvc_cb[i + 1].in_use &&
+ attr_id >= p_cb->srvc_cb[i].service_id) ||
+ /* last service incb */
+ (i == (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+ attr_id >= p_cb->srvc_cb[i].service_id)
+ )
+ {
+ return &p_cb->srvc_cb[i];
+ }
+ }
+ return NULL;
+}
+/*******************************************************************************
+**
+** Function bta_gatts_uuid_compare
+**
+** Description Compare two UUID to see if they are the same.
+**
+** Returns TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src)
+{
+ UINT8 su[LEN_UUID_128], tu[LEN_UUID_128];
+ UINT8 *ps, *pt;
+
+ /* any of the UUID is unspecified */
+ if (src.len == 0 || tar.len == 0)
+ {
+ return TRUE;
+ }
+
+ /* If both are 16-bit, we can do a simple compare */
+ if (src.len == 2 && tar.len == 2)
+ {
+ return src.uu.uuid16 == tar.uu.uuid16;
+ }
+
+ /* One or both of the UUIDs is 128-bit */
+ if (src.len == LEN_UUID_16)
+ {
+ /* convert a 16 bits UUID to 128 bits value */
+ bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
+ ps = su;
+ }
+ else
+ ps = src.uu.uuid128;
+
+ if (tar.len == LEN_UUID_16)
+ {
+ /* convert a 16 bits UUID to 128 bits value */
+ bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
+ pt = tu;
+ }
+ else
+ pt = tar.uu.uuid128;
+
+ return(memcmp(ps, pt, LEN_UUID_128) == 0);
+}
+
+
+
+
+#endif
diff --git a/bta/hh/bta_hh_act.c b/bta/hh/bta_hh_act.c
new file mode 100644
index 0000000..de08096
--- /dev/null
+++ b/bta/hh/bta_hh_act.c
@@ -0,0 +1,1197 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the HID host action functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_sys.h"
+#include "btm_api.h"
+#include "l2c_api.h"
+#include "bta_hh_int.h"
+#include "bta_hh_co.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+static void bta_hh_cback (UINT8 dev_handle, UINT8 event, UINT32 data,
+ BT_HDR *pdata);
+static tBTA_HH_STATUS bta_hh_get_trans_status(UINT32 result);
+
+#if BTA_HH_DEBUG
+static char* bta_hh_get_w4_event(UINT16 event);
+static char * bta_hh_hid_event_name(UINT16 event);
+#endif
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_hh_api_enable
+**
+** Description Perform necessary operations to enable HID host.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_api_enable(tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_STATUS status = BTA_HH_ERR;
+ UINT8 xx;
+
+ /* initialize BTE HID */
+ HID_HostInit();
+
+ memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
+
+ HID_HostSetSecurityLevel("", p_data->api_enable.sec_mask);
+
+ /* Register with L2CAP */
+ if ( HID_HostRegister (bta_hh_cback) == HID_SUCCESS)
+ {
+ /* store parameters */
+ bta_hh_cb.p_cback = p_data->api_enable.p_cback;
+
+ status = BTA_HH_OK;
+ /* initialize device CB */
+ for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+ {
+ bta_hh_cb.kdev[xx].state = BTA_HH_IDLE_ST;
+ bta_hh_cb.kdev[xx].hid_handle = BTA_HH_INVALID_HANDLE;
+ bta_hh_cb.kdev[xx].index = xx;
+ /* initialize control block map */
+ bta_hh_cb.cb_index[xx] = BTA_HH_MAX_KNOWN;
+ }
+ }
+
+ /* signal BTA call back event */
+ (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
+}
+/*******************************************************************************
+**
+** Function bta_hh_api_disable
+**
+** Description Perform necessary operations to disable HID host.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_api_disable(void)
+{
+ UINT8 xx;
+
+ /* service is not enabled */
+ if (bta_hh_cb.p_cback == NULL)
+ return;
+
+ /* no live connection, signal DISC_CMPL_EVT directly */
+ if (!bta_hh_cb.cnt_num)
+ {
+ bta_hh_disc_cmpl();
+ }
+ else /* otherwise, disconnect all live connections */
+ {
+ bta_hh_cb.w4_disable = TRUE;
+
+ for(xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+ {
+ /* send API_CLOSE event to every connected device */
+ if ( bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST )
+ {
+ /* disconnect all connected devices */
+ bta_hh_sm_execute(&bta_hh_cb.kdev[xx],
+ BTA_HH_API_CLOSE_EVT,
+ NULL);
+ }
+ }
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_disc_cmpl
+**
+** Description All connections have been closed, disable service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_disc_cmpl(void)
+{
+ UINT8 xx;
+ tBTA_HH_STATUS status = BTA_HH_OK;
+
+ /* Deregister with lower layer */
+ if (HID_HostDeregister()!= HID_SUCCESS)
+ status = BTA_HH_ERR;
+
+ /* free buffer in CB holding report descriptors */
+ for(xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+ {
+ utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
+ }
+ utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+
+ (* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status);
+ /* all connections are down, no waiting for diconnect */
+ memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
+}
+/*******************************************************************************
+**
+** Function bta_hh_sdp_cback
+**
+** Description SDP callback function.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask,
+ tHID_DEV_SDP_INFO *sdp_rec )
+{
+ tBTA_HH_DEV_CB *p_cb = bta_hh_cb.p_cur;
+ UINT8 hdl;
+ tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
+
+ if (result == SDP_SUCCESS)
+ {
+ /* security is required for the connection, add attr_mask bit*/
+ if (p_cb->sec_mask)
+ attr_mask |= HID_SEC_REQUIRED;
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_EVENT3("bta_hh_sdp_cback: p_cb: %d result 0x%02x, \
+ attr_mask 0x%02x", \
+ p_cb, result, attr_mask);
+#endif
+
+ /* check to see type of device is supported , and should not been added before */
+ if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class))
+ {
+ /* if not added before */
+ if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+ {
+ /* add device/update attr_mask information */
+ if(HID_HostAddDev (p_cb->addr, attr_mask, &hdl) == HID_SUCCESS)
+ {
+ status = BTA_HH_OK;
+ /* update cb_index[] map */
+ bta_hh_cb.cb_index[hdl] = p_cb->index;
+ }
+ else
+ {
+ p_cb->app_id = 0;
+ }
+ }
+ /* else : incoming connection after SDP should update the SDP information as well */
+
+ if (p_cb->app_id != 0)
+ {
+ /* update cb information with attr_mask, dscp_info etc. */
+ bta_hh_add_device_to_list(p_cb, hdl, attr_mask,
+ &sdp_rec->dscp_info,
+ sdp_rec->sub_class,
+ sdp_rec->ssr_max_latency,
+ sdp_rec->ssr_min_tout,
+ p_cb->app_id);
+
+ p_cb->dscp_info.ctry_code = sdp_rec->ctry_code;
+
+ status = BTA_HH_OK;
+ }
+
+ }
+ else /* type of device is not supported */
+ status = BTA_HH_ERR_TOD_UNSPT;
+ }
+
+ /* free disc_db when SDP is completed */
+ utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+
+
+ /* send SDP_CMPL_EVT into state machine */
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+ return;
+}
+/*******************************************************************************
+**
+** Function bta_hh_di_sdp_cback
+**
+** Description SDP DI callback function.
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hh_di_sdp_cback(UINT16 result)
+{
+ tBTA_HH_DEV_CB *p_cb = bta_hh_cb.p_cur;
+ tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
+ tSDP_DI_GET_RECORD di_rec;
+ tHID_STATUS ret;
+#if BTA_HH_DEBUG
+ APPL_TRACE_EVENT2("bta_hh_di_sdp_cback: p_cb: %d result 0x%02x", p_cb, result);
+#endif
+ /* if DI record does not exist on remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be
+ * set to 0xffff and we will allow the connection to go through. Spec mandates that DI
+ * record be set, but many HID devices do not set this. So for IOP purposes, we allow the
+ * connection to go through and update the DI record to invalid DI entry.*/
+ if ((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH))
+ {
+ if(result == SDP_SUCCESS && SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0)
+ {
+ /* always update information with primary DI record */
+ if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS)
+ {
+ bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version);
+ }
+
+ }
+ else /* no DI recrod available */
+ {
+ bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0);
+ }
+
+ if ((ret = HID_HostGetSDPRecord(p_cb->addr,
+ bta_hh_cb.p_disc_db,
+ p_bta_hh_cfg->sdp_db_size,
+ bta_hh_sdp_cback)) == HID_SUCCESS)
+ {
+ status = BTA_HH_OK;
+ }
+ else
+ {
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1 ("bta_hh_di_sdp_cback: HID_HostGetSDPRecord failed: Status 0x%2x",
+ ret);
+#endif
+ }
+ }
+
+
+ if (status != BTA_HH_OK)
+ {
+ utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+ /* send SDP_CMPL_EVT into state machine */
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+ }
+ return;
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hh_start_sdp
+**
+** Description Start SDP service search, and obtain necessary SDP records.
+** Only one SDP service search request is allowed at the same
+** time. For every BTA_HhOpen API call, do SDP first unless SDP
+** has been done previously.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_STATUS status = BTA_HH_ERR_SDP;
+ UINT8 hdl;
+
+ p_cb->sec_mask = p_data->api_conn.sec_mask;
+ p_cb->mode = p_data->api_conn.mode;
+
+ /* if previously virtually cabled device, skip SDP */
+ if (p_cb->app_id)
+ {
+ status = BTA_HH_OK;
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG0("bta_hh_start_sdp:: skip SDP for known devices");
+#endif
+ if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+ {
+ if ((HID_HostAddDev (p_cb->addr, p_cb->attr_mask, &hdl)) \
+ == HID_SUCCESS)
+ {
+ /* update device CB with newly register device handle */
+ bta_hh_add_device_to_list(p_cb, hdl, p_cb->attr_mask, NULL,
+ p_cb->sub_class,
+ p_cb->dscp_info.ssr_max_latency,
+ p_cb->dscp_info.ssr_min_tout,
+ p_cb->app_id);
+ /* update cb_index[] map */
+ bta_hh_cb.cb_index[hdl] = p_cb->index;
+ }
+ else
+ {
+ status = BTA_HH_ERR_SDP;
+ }
+ }
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+ return;
+ }
+ /* GetSDPRecord. at one time only one SDP precedure can be active */
+ else if (!bta_hh_cb.p_disc_db)
+ {
+ bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(p_bta_hh_cfg->sdp_db_size);
+
+ if (bta_hh_cb.p_disc_db == NULL)
+ {
+ status = BTA_HH_ERR_NO_RES;
+ }
+ else
+ {
+ bta_hh_cb.p_cur = p_cb;
+ /* do DI discovery first */
+ if (SDP_DiDiscover(p_data->api_conn.bd_addr,
+ bta_hh_cb.p_disc_db,
+ p_bta_hh_cfg->sdp_db_size,
+ bta_hh_di_sdp_cback) != SDP_SUCCESS)
+ {
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1 ("bta_hh_start_sdp: SDP_DiDiscover failed: \
+ Status 0x%2X",status);
+#endif
+ status = BTA_HH_ERR_SDP;
+ utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+ }
+ else
+ status = BTA_HH_OK;
+ }
+ }
+
+ if (status != BTA_HH_OK)
+ bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+ return;
+
+}
+/*******************************************************************************
+**
+** Function bta_hh_sdp_cmpl
+**
+** Description When SDP completed, initiate a connection or report error depend
+** on SDP result.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_CONN conn_dat;
+ tBTA_HH_STATUS status = p_data->status;
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1 ("bta_hh_sdp_cmpl: status 0x%2X",p_data->status);
+#endif
+
+ /* initialize call back data */
+ memset((void *)&conn_dat, 0, sizeof(tBTA_HH_CONN));
+ conn_dat.handle = p_cb->hid_handle;
+ bdcpy(conn_dat.bda, p_cb->addr);
+
+ /* if SDP compl success */
+ if ( status == BTA_HH_OK)
+ {
+ /* not incoming connection doing SDP, initiate a HID connection */
+ if (!p_cb->incoming_conn)
+ {
+ tHID_STATUS ret;
+ /* set security level */
+ HID_HostSetSecurityLevel("", p_cb->sec_mask);
+
+ /* open HID connection */
+ if ((ret = HID_HostOpenDev (p_cb->hid_handle)) != HID_SUCCESS)
+ {
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1 ("bta_hh_sdp_cmpl: HID_HostOpenDev failed: \
+ Status 0x%2X",ret);
+#endif
+ /* open fail, remove device from management device list */
+ HID_HostRemoveDev( p_cb->hid_handle);
+ status = BTA_HH_ERR;
+ }
+ else
+ {
+ status = BTA_HH_OK;
+ }
+ }
+ else /* incoming connection SDP finish */
+ {
+ bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
+ }
+ }
+
+ if (status != BTA_HH_OK)
+ {
+ conn_dat.status = status;
+
+ (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+ /* move state machine W4_CONN ->IDLE */
+ bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
+
+ /* if this is an outgoing connection to an unknown device, clean up cb */
+ if (p_cb->app_id == 0 && !p_cb->incoming_conn)
+ {
+ /* clean up device control block */
+ bta_hh_clean_up_kdev(p_cb);
+ }
+
+#if BTA_HH_DEBUG
+ bta_hh_trace_dev_db();
+#endif
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_api_disc_act
+**
+** Description HID Host initiate a disconnection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_api_disc_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_CBDATA disc_dat;
+ tHID_STATUS status;
+
+ /* found an active connection */
+ disc_dat.handle = p_data ?(UINT8)p_data->hdr.layer_specific :p_cb->hid_handle;
+ disc_dat.status = BTA_HH_ERR;
+
+ status = HID_HostCloseDev(disc_dat.handle);
+
+ if (status)
+ (* bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
+
+ return;
+}
+/*******************************************************************************
+**
+** Function bta_hh_open_cmpl_act
+**
+** Description HID host connection completed
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_CONN conn ;
+ UINT8 dev_handle = p_data ? (UINT8)p_data->hid_cback.hdr.layer_specific : \
+ p_cb->hid_handle;
+
+ memset((void *)&conn, 0, sizeof (tBTA_HH_CONN));
+ conn.handle = dev_handle;
+ bdcpy(conn.bda, p_cb->addr);
+
+ /* increase connection number */
+ bta_hh_cb.cnt_num ++;
+
+ /* initialize device driver */
+ bta_hh_co_open(p_cb->hid_handle, p_cb->sub_class,
+ p_cb->attr_mask, p_cb->app_id);
+
+ /* update SSR settings */
+ bta_sys_chg_ssr_config(BTA_ID_HH ,p_cb->app_id, p_cb->dscp_info.ssr_max_latency, p_cb->dscp_info.ssr_min_tout);
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
+
+ /* set protocol mode when not default report mode */
+ if (p_cb->mode != BTA_HH_PROTO_RPT_MODE)
+ {
+ if ((HID_HostWriteDev(dev_handle,
+ HID_TRANS_SET_PROTOCOL, HID_PAR_PROTOCOL_BOOT_MODE,
+ 0,
+ 0, NULL)) != HID_SUCCESS)
+ {
+ /* HID connection is up, while SET_PROTO fail */
+ conn.status = BTA_HH_ERR_PROTO;
+ (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
+ }
+ else
+ {
+ conn.status = BTA_HH_OK;
+ p_cb->w4_evt = BTA_HH_OPEN_EVT;
+ }
+ }
+ else
+ (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
+
+ p_cb->incoming_conn = FALSE;
+
+}
+/*******************************************************************************
+**
+** Function bta_hh_open_act
+**
+** Description HID host receive HID_OPEN_EVT .
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_API_CONN conn_data;
+
+#if BTA_HH_DEBUG
+ UINT8 dev_handle = p_data ? (UINT8)p_data->hid_cback.hdr.layer_specific : \
+ p_cb->hid_handle;
+
+ APPL_TRACE_EVENT1 ("bta_hh_open_act: Device[%d] connected", dev_handle);
+#endif
+
+ /* SDP has been done */
+ if (p_cb->app_id != 0)
+ {
+ bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
+ }
+ else
+ /* app_id == 0 indicates an incoming conenction request arrives without SDP
+ performed, do it first */
+ {
+ p_cb->incoming_conn = TRUE;
+
+ memset(&conn_data, 0, sizeof(tBTA_HH_API_CONN));
+ bdcpy(conn_data.bd_addr, p_cb->addr);
+ bta_hh_start_sdp(p_cb, (tBTA_HH_DATA *)&conn_data);
+ }
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hh_data_act
+**
+** Description HID Host process a data report
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+ BT_HDR *pdata = p_data->hid_cback.p_data;
+ UINT8 *p_rpt = (UINT8 *)(pdata + 1) + pdata->offset;
+
+ bta_hh_co_data((UINT8)p_data->hid_cback.hdr.layer_specific, p_rpt, pdata->len,
+ p_cb->mode, p_cb->sub_class, p_cb->dscp_info.ctry_code, p_cb->addr, p_cb->app_id);
+
+ utl_freebuf((void **)&pdata);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hh_handsk_act
+**
+** Description HID Host process a handshake acknoledgement.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+ tBTA_HH_CBDATA cback_data ;
+ tBTA_HH_HSDATA hs_data;
+ tBTA_HH_CONN conn ;
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG2("HANDSHAKE received for: event = %s data= %d",
+ bta_hh_get_w4_event(p_cb->w4_evt), p_data->hid_cback.data);
+#endif
+
+ memset(&hs_data, 0, sizeof(tBTA_HH_HSDATA));
+
+ switch (p_cb->w4_evt)
+ {
+ /* GET_ transsaction, handshake indicate unsupported request */
+ case BTA_HH_GET_PROTO_EVT:
+ hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
+ /* fall through */
+ case BTA_HH_GET_RPT_EVT:
+ case BTA_HH_GET_IDLE_EVT :
+ hs_data.handle = p_cb->hid_handle;
+ /* if handshake gives an OK code for these transaction, fill in UNSUPT */
+ if ((hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data)) == BTA_HH_OK)
+ hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
+
+ (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
+ p_cb->w4_evt = 0;
+ break;
+
+ /* acknoledgement from HID device for SET_ transaction */
+ case BTA_HH_SET_RPT_EVT:
+ case BTA_HH_SET_PROTO_EVT:
+ case BTA_HH_SET_IDLE_EVT :
+ cback_data.handle = p_cb->hid_handle;
+ cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
+ (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&cback_data);
+ p_cb->w4_evt = 0;
+ break;
+
+ /* SET_PROTOCOL when open connection */
+ case BTA_HH_OPEN_EVT:
+ conn.status =p_data->hid_cback.data ? BTA_HH_ERR_PROTO: BTA_HH_OK;
+ conn.handle = p_cb->hid_handle;
+ bdcpy(conn.bda, p_cb->addr);
+ (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn);
+#if BTA_HH_DEBUG
+ bta_hh_trace_dev_db();
+#endif
+ p_cb->w4_evt = 0;
+ break;
+
+ default:
+ /* unknow transaction handshake response */
+ APPL_TRACE_DEBUG0("unknown transaction type");
+ break;
+ }
+
+ /* transaction achknoledgement received, inform PM for mode change */
+ bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+ return;
+}
+/*******************************************************************************
+**
+** Function bta_hh_ctrl_dat_act
+**
+** Description HID Host process a data report from control channel.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+ BT_HDR *pdata = p_data->hid_cback.p_data;
+ UINT8 *data = (UINT8 *)(pdata + 1) + pdata->offset;
+ tBTA_HH_HSDATA hs_data;
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1("Ctrl DATA received w4: event[%s]",
+ bta_hh_get_w4_event(p_cb->w4_evt));
+#endif
+ hs_data.status = BTA_HH_OK;
+ hs_data.handle = p_cb->hid_handle;
+
+ switch (p_cb->w4_evt)
+ {
+ case BTA_HH_GET_IDLE_EVT:
+ hs_data.rsp_data.idle_rate = *data;
+ break;
+ case BTA_HH_GET_RPT_EVT:
+ hs_data.rsp_data.p_rpt_data = pdata;
+ break;
+ case BTA_HH_GET_PROTO_EVT:
+ /* match up BTE/BTA report/boot mode def*/
+ hs_data.rsp_data.proto_mode = ((*data) == HID_PAR_PROTOCOL_REPORT)? \
+ BTA_HH_PROTO_RPT_MODE : BTA_HH_PROTO_BOOT_MODE;
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1("GET_PROTOCOL Mode = [%s]",
+ (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
+#endif
+ break;
+ /* should not expect control DATA for SET_ transaction */
+ case BTA_HH_SET_PROTO_EVT:
+ /* fall through */
+ case BTA_HH_SET_RPT_EVT:
+ /* fall through */
+ case BTA_HH_SET_IDLE_EVT :
+ /* fall through */
+ default:
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1("invalid transaction type for DATA payload: 4_evt[%s]",
+ bta_hh_get_w4_event(p_cb->w4_evt));
+#endif
+ break;
+ }
+
+ /* inform PM for mode change */
+ bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+ bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+
+ (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
+
+ p_cb->w4_evt = 0;
+ utl_freebuf((void **)&pdata);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_close_act
+**
+** Description HID Host process a close event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_CONN conn_dat ;
+ tBTA_HH_CBDATA disc_dat = {BTA_HH_OK, 0};
+ UINT32 reason = p_data->hid_cback.data; /* Reason for closing (32-bit) */
+
+ /* if HID_HDEV_EVT_VC_UNPLUG was received, report BTA_HH_VC_UNPLUG_EVT */
+ UINT16 event = p_cb->vp ? BTA_HH_VC_UNPLUG_EVT : BTA_HH_CLOSE_EVT;
+
+ disc_dat.handle = p_cb->hid_handle;
+ disc_dat.status = p_data->hid_cback.data;
+
+ /* Check reason for closing */
+ if ((reason & (HID_L2CAP_CONN_FAIL|HID_L2CAP_REQ_FAIL)) || /* Failure to initialize connection (page timeout or l2cap error) */
+ (reason == HID_ERR_AUTH_FAILED) || /* Authenication error (while initiating) */
+ (reason == HID_ERR_L2CAP_FAILED)) /* Failure creating l2cap connection */
+ {
+ /* Failure in opening connection */
+ conn_dat.handle = p_cb->hid_handle;
+ conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
+ bdcpy(conn_dat.bda, p_cb->addr);
+ HID_HostCloseDev(p_cb->hid_handle);
+
+ /* Report OPEN fail event */
+ (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+#if BTA_HH_DEBUG
+ bta_hh_trace_dev_db();
+#endif
+ return;
+ }
+ /* otherwise report CLOSE/VC_UNPLUG event */
+ else
+ {
+ /* finaliza device driver */
+ bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
+ /* update total conn number */
+ bta_hh_cb.cnt_num --;
+
+ if (disc_dat.status)
+ disc_dat.status = BTA_HH_ERR;
+
+ (*bta_hh_cb.p_cback)(event, (tBTA_HH *)&disc_dat);
+
+ /* if virtually unplug, remove device */
+ if (p_cb->vp )
+ {
+ HID_HostRemoveDev( p_cb->hid_handle);
+ bta_hh_clean_up_kdev(p_cb);
+ }
+
+#if BTA_HH_DEBUG
+ bta_hh_trace_dev_db();
+#endif
+ }
+
+ /* clean up control block, but retain SDP info and device handle */
+ p_cb->vp = FALSE;
+ p_cb->w4_evt = 0;
+
+ /* if no connection is active and HH disable is signaled, disable service */
+ if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
+ {
+ bta_hh_disc_cmpl();
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_get_dscp_act
+**
+** Description Get device report descriptor
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_get_dscp_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_maint_dev_act
+**
+** Description HID Host maintain device list.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_MAINT_DEV *p_dev_info = &p_data->api_maintdev;
+ tBTA_HH_DEV_INFO dev_info ;
+ UINT8 dev_handle;
+
+ dev_info.status = BTA_HH_ERR;
+ dev_info.handle = BTA_HH_INVALID_HANDLE;
+
+ switch (p_dev_info->sub_event)
+ {
+ case BTA_HH_ADD_DEV_EVT: /* add a device */
+ bdcpy(dev_info.bda, p_dev_info->bda);
+ /* initialize callback data */
+ if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+ {
+ if (HID_HostAddDev(p_dev_info->bda, p_dev_info->attr_mask, &dev_handle)\
+ == HID_SUCCESS)
+ {
+ dev_info.handle = dev_handle;
+ dev_info.status = BTA_HH_OK;
+
+ /* update DI information */
+ bta_hh_update_di_info(p_cb,
+ p_dev_info->dscp_info.vendor_id,
+ p_dev_info->dscp_info.product_id,
+ p_dev_info->dscp_info.version);
+
+ /* add to BTA device list */
+ bta_hh_add_device_to_list(p_cb, dev_handle,
+ p_dev_info->attr_mask,
+ &p_dev_info->dscp_info.descriptor,
+ p_dev_info->sub_class,
+ p_dev_info->dscp_info.ssr_max_latency,
+ p_dev_info->dscp_info.ssr_min_tout,
+ p_dev_info->app_id);
+ /* update cb_index[] map */
+ bta_hh_cb.cb_index[dev_handle] = p_cb->index;
+ }
+ }
+ else /* device already been added */
+ {
+ dev_info.handle = p_cb->hid_handle;
+ dev_info.status = BTA_HH_OK;
+ }
+#if BTA_HH_DEBUG
+ bta_hh_trace_dev_db();
+#endif
+ break;
+
+ case BTA_HH_RMV_DEV_EVT: /* remove device */
+ dev_info.handle = (UINT8)p_dev_info->hdr.layer_specific;
+
+ bdcpy(dev_info.bda, p_cb->addr);
+ if (p_cb->state != BTA_HH_CONN_ST )
+ {
+ if(HID_HostRemoveDev( dev_info.handle ) == HID_SUCCESS)
+ {
+ dev_info.status = BTA_HH_OK;
+
+ /* remove from known device list in BTA */
+ bta_hh_clean_up_kdev(p_cb);
+ }
+ }
+ break;
+
+ default:
+ APPL_TRACE_DEBUG0("invalid command");
+ break;
+ }
+
+ (* bta_hh_cb.p_cback)(p_dev_info->sub_event, (tBTA_HH *)&dev_info);
+}
+/*******************************************************************************
+**
+** Function bta_hh_write_dev_act
+**
+** Description Write device action. can be SET/GET/DATA transaction.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+ tBTA_HH_CBDATA cbdata = {BTA_HH_OK, 0};
+ UINT16 event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
+ BTA_HH_FST_TRANS_CB_EVT;
+
+ cbdata.handle = p_cb->hid_handle;
+
+ /* match up BTE/BTA report/boot mode def */
+ if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL)
+ {
+ p_data->api_sndcmd.param = ( p_data->api_sndcmd.param == BTA_HH_PROTO_RPT_MODE) ?\
+ HID_PAR_PROTOCOL_REPORT :HID_PAR_PROTOCOL_BOOT_MODE;
+ }
+
+ if (HID_HostWriteDev (p_cb->hid_handle,
+ p_data->api_sndcmd.t_type,
+ p_data->api_sndcmd.param,
+ p_data->api_sndcmd.data,
+ p_data->api_sndcmd.rpt_id,
+ p_data->api_sndcmd.p_data) != HID_SUCCESS)
+ {
+ APPL_TRACE_ERROR0("HID_HostWriteDev Error ");
+ cbdata.status = BTA_HH_ERR;
+
+ if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL &&
+ p_data->api_sndcmd.t_type != HID_TRANS_DATA)
+ (* bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata);
+ else if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+ (* bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, (tBTA_HH *)&cbdata);
+ }
+ else
+ {
+
+ switch(p_data->api_sndcmd.t_type)
+ {
+ case HID_TRANS_SET_PROTOCOL:
+ /* fall through */
+ case HID_TRANS_GET_REPORT:
+ /* fall through */
+ case HID_TRANS_SET_REPORT:
+ /* fall through */
+ case HID_TRANS_GET_PROTOCOL:
+ /* fall through */
+ case HID_TRANS_GET_IDLE:
+ /* fall through */
+ case HID_TRANS_SET_IDLE:/* set w4_handsk event name for callback function use */
+ p_cb->w4_evt = event;
+ break;
+ case HID_TRANS_DATA: /* output report */
+ /* fall through */
+ case HID_TRANS_CONTROL:
+ /* no handshake event will be generated */
+ /* if VC_UNPLUG is issued, set flag */
+ if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+ p_cb->vp = TRUE;
+
+ break;
+ /* currently not expected */
+ case HID_TRANS_DATAC:
+ default:
+ APPL_TRACE_DEBUG1("bta_hh_write_dev_act:: cmd type = %d",
+ p_data->api_sndcmd.t_type);
+ break;
+ }
+
+ /* if not control type transaction, notify PM for energy control */
+ if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
+ {
+ /* inform PM for mode change */
+ bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+ bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+ }
+ else if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND)
+ {
+ bta_sys_sco_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+ }
+ else if (p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
+ {
+ bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+ }
+ }
+
+
+ return;
+}
+
+/*****************************************************************************
+** Static Function
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_hh_cback
+**
+** Description BTA HH callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hh_cback (UINT8 dev_handle, UINT8 event, UINT32 data,
+ BT_HDR *pdata)
+{
+ tBTA_HH_CBACK_DATA *p_buf = NULL;
+ UINT16 sm_event = BTA_HH_INVALID_EVT;
+ UINT8 xx = 0;
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1("bta_hh_cback::HID_event [%s]", bta_hh_hid_event_name(event));
+#endif
+
+ switch (event)
+ {
+ case HID_HDEV_EVT_OPEN:
+ sm_event = BTA_HH_INT_OPEN_EVT;
+ break;
+ case HID_HDEV_EVT_CLOSE:
+ sm_event = BTA_HH_INT_CLOSE_EVT;
+ break;
+ case HID_HDEV_EVT_INTR_DATA:
+ sm_event = BTA_HH_INT_DATA_EVT;
+ break;
+ case HID_HDEV_EVT_HANDSHAKE:
+ sm_event = BTA_HH_INT_HANDSK_EVT;
+ break;
+ case HID_HDEV_EVT_CTRL_DATA:
+ sm_event = BTA_HH_INT_CTRL_DATA;
+ break;
+ case HID_HDEV_EVT_RETRYING:
+ break;
+ case HID_HDEV_EVT_INTR_DATC:
+ case HID_HDEV_EVT_CTRL_DATC:
+ /* Unhandled events: Free buffer for DATAC */
+ utl_freebuf((void **)&pdata);
+ break;
+ case HID_HDEV_EVT_VC_UNPLUG:
+ for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+ {
+ if (bta_hh_cb.kdev[xx].hid_handle == dev_handle)
+ {
+ bta_hh_cb.kdev[xx].vp = TRUE;
+ break;
+ }
+ }
+ break;
+ }
+
+ if (sm_event != BTA_HH_INVALID_EVT &&
+ (p_buf = (tBTA_HH_CBACK_DATA *)GKI_getbuf(sizeof(tBTA_HH_CBACK_DATA) +
+ sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->hdr.event = sm_event;
+ p_buf->hdr.layer_specific = (UINT16)dev_handle;
+ p_buf->data = data;
+ p_buf->p_data = pdata;
+
+ bta_sys_sendmsg(p_buf);
+ }
+
+}
+/*******************************************************************************
+**
+** Function bta_hh_get_trans_status
+**
+** Description translate a handshake result code into BTA HH
+** status code
+**
+*******************************************************************************/
+static tBTA_HH_STATUS bta_hh_get_trans_status(UINT32 result)
+{
+ switch(result)
+ {
+ case HID_PAR_HANDSHAKE_RSP_SUCCESS : /* (0) */
+ return BTA_HH_OK;
+ case HID_PAR_HANDSHAKE_RSP_NOT_READY : /* (1) */
+ case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID: /* (2) */
+ case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ : /* (3) */
+ case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM : /* (4) */
+ return (tBTA_HH_STATUS)result;
+ case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN : /* (14) */
+ case HID_PAR_HANDSHAKE_RSP_ERR_FATAL : /* (15) */
+ default:
+ return BTA_HH_HS_ERROR;
+ break;
+ }
+}
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+
+#if (defined BTA_HH_DEBUG && BTA_HH_DEBUG == TRUE)
+static char* bta_hh_get_w4_event(UINT16 event)
+{
+ switch (event)
+ {
+ case BTA_HH_GET_RPT_EVT:
+ return "BTA_HH_GET_RPT_EVT";
+ case BTA_HH_SET_RPT_EVT:
+ return "BTA_HH_SET_RPT_EVT";
+ case BTA_HH_GET_PROTO_EVT:
+ return "BTA_HH_GET_PROTO_EVT";
+ case BTA_HH_SET_PROTO_EVT:
+ return "BTA_HH_SET_PROTO_EVT";
+ case BTA_HH_GET_IDLE_EVT:
+ return "BTA_HH_GET_IDLE_EVT";
+ case BTA_HH_SET_IDLE_EVT:
+ return "BTA_HH_SET_IDLE_EVT";
+ case BTA_HH_OPEN_EVT:
+ return "BTA_HH_OPEN_EVT";
+ default:
+ return "Unknown event";
+ }
+
+}
+
+static char * bta_hh_hid_event_name(UINT16 event)
+{
+ switch (event)
+ {
+ case HID_HDEV_EVT_OPEN:
+ return "HID_HDEV_EVT_OPEN";
+ case HID_HDEV_EVT_CLOSE:
+ return "HID_HDEV_EVT_CLOSE";
+ case HID_HDEV_EVT_RETRYING:
+ return "HID_HDEV_EVT_RETRYING";
+ case HID_HDEV_EVT_INTR_DATA:
+ return "HID_HDEV_EVT_INTR_DATA";
+ case HID_HDEV_EVT_INTR_DATC:
+ return "HID_HDEV_EVT_INTR_DATC";
+ case HID_HDEV_EVT_CTRL_DATA:
+ return "HID_HDEV_EVT_CTRL_DATA";
+ case HID_HDEV_EVT_CTRL_DATC:
+ return "HID_HDEV_EVT_CTRL_DATC";
+ case HID_HDEV_EVT_HANDSHAKE:
+ return "HID_HDEV_EVT_HANDSHAKE";
+ case HID_HDEV_EVT_VC_UNPLUG:
+ return "HID_HDEV_EVT_VC_UNPLUG";
+ default:
+ return "Unknown HID event";
+ }
+}
+#endif
+#endif /* BTA_HH_INCLUDED */
+
diff --git a/bta/hh/bta_hh_api.c b/bta/hh/bta_hh_api.c
new file mode 100644
index 0000000..300fc6f
--- /dev/null
+++ b/bta/hh/bta_hh_api.c
@@ -0,0 +1,447 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the HID HOST API in the subsystem of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "bta_hh_api.h"
+#include "bta_hh_int.h"
+#include "l2c_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_hh_reg =
+{
+ bta_hh_hdl_event,
+ BTA_HhDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_HhEnable
+**
+** Description Enable the HID host. This function must be called before
+** any other functions in the HID host API are called. When the
+** enable operation is complete the callback function will be
+** called with BTA_HH_ENABLE_EVT.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback)
+{
+ tBTA_HH_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_HH, &bta_hh_reg);
+ GKI_sched_unlock();
+
+ APPL_TRACE_ERROR0("Calling BTA_HhEnable");
+ p_buf = (tBTA_HH_API_ENABLE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_ENABLE));
+
+ if (p_buf != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));
+
+ p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->sec_mask = sec_mask;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HhDisable
+**
+** Description Disable the HID host. If the server is currently
+** connected, the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_HH);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_HH_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HhClose
+**
+** Description Disconnect a connection.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhClose(UINT8 dev_handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)sizeof(BT_HDR))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(BT_HDR));
+ p_buf->event = BTA_HH_API_CLOSE_EVT;
+ p_buf->layer_specific = (UINT16) dev_handle;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HhOpen
+**
+** Description Connect to a device of specified BD address in specified
+** protocol mode and security level.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhOpen(BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode, tBTA_SEC sec_mask)
+{
+ tBTA_HH_API_CONN *p_buf;
+
+ p_buf = (tBTA_HH_API_CONN *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_CONN));
+
+ if (p_buf!= NULL)
+ {
+ memset((void *)p_buf, 0, sizeof(tBTA_HH_API_CONN));
+
+ p_buf->hdr.event = BTA_HH_API_OPEN_EVT;
+ p_buf->hdr.layer_specific = BTA_HH_INVALID_HANDLE;
+ p_buf->sec_mask = sec_mask;
+ p_buf->mode = mode;
+ bdcpy(p_buf->bd_addr, dev_bda);
+
+ bta_sys_sendmsg((void *)p_buf);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("No resource to send HID host Connect request.");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_snd_write_dev
+**
+*******************************************************************************/
+static void bta_hh_snd_write_dev(UINT8 dev_handle, UINT8 t_type, UINT8 param,
+ UINT16 data, UINT8 rpt_id, BT_HDR *p_data)
+{
+ tBTA_HH_CMD_DATA *p_buf;
+ UINT16 len = (UINT16) (sizeof(tBTA_HH_CMD_DATA) );
+
+ if ((p_buf = (tBTA_HH_CMD_DATA *)GKI_getbuf(len))!= NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_HH_CMD_DATA));
+
+ p_buf->hdr.event = BTA_HH_API_WRITE_DEV_EVT;
+ p_buf->hdr.layer_specific = (UINT16) dev_handle;
+ p_buf->t_type = t_type;
+ p_buf->data = data;
+ p_buf->param = param;
+ p_buf->p_data = p_data;
+ p_buf->rpt_id = rpt_id;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_HhSetReport
+**
+** Description send SET_REPORT to device.
+**
+** Parameter dev_handle: device handle
+** r_type: report type, could be BTA_HH_RPTT_OUTPUT or
+** BTA_HH_RPTT_FEATURE.
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhSetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, BT_HDR *p_data)
+{
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_REPORT, r_type, 0, 0, p_data);
+}
+/*******************************************************************************
+**
+** Function BTA_HhGetReport
+**
+** Description Send a GET_REPORT to HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id, UINT16 buf_size)
+{
+ UINT8 param = (buf_size) ? (r_type | 0x08) : r_type;
+
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_REPORT, param,
+ buf_size, rpt_id, NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_HhSetProtoMode
+**
+** Description This function set the protocol mode at specified HID handle
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhSetProtoMode(UINT8 dev_handle, tBTA_HH_PROTO_MODE p_type)
+{
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_PROTOCOL, (UINT8)p_type,
+ 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_HhGetProtoMode
+**
+** Description This function get protocol mode information.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhGetProtoMode(UINT8 dev_handle)
+{
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_PROTOCOL, 0, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_HhSetIdle
+**
+** Description send SET_IDLE to device.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate)
+{
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_IDLE, 0, idle_rate, 0, NULL);
+}
+
+/*******************************************************************************
+**
+** Function BTA_HhGetIdle
+**
+** Description Send a GET_IDLE from HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhGetIdle(UINT8 dev_handle)
+{
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_IDLE, 0, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_HhSendCtrl
+**
+** Description Send a control command to HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhSendCtrl(UINT8 dev_handle, tBTA_HH_TRANS_CTRL_TYPE c_type)
+{
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_CONTROL, (UINT8)c_type, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_HhSendData
+**
+** Description This function send DATA transaction to HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR *p_data)
+{
+ bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, BTA_HH_RPTT_OUTPUT, 0, 0, p_data);
+}
+
+/*******************************************************************************
+**
+** Function BTA_HhGetDscpInfo
+**
+** Description Get HID device report descriptor
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhGetDscpInfo(UINT8 dev_handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)sizeof(BT_HDR))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(BT_HDR));
+ p_buf->event = BTA_HH_API_GET_DSCP_EVT;
+ p_buf->layer_specific = (UINT16) dev_handle;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HhAddDev
+**
+** Description Add a virtually cabled device into HID-Host device list
+** to manage and assign a device handle for future API call,
+** host applciation call this API at start-up to initialize its
+** virtually cabled devices.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask, UINT8 sub_class,
+ UINT8 app_id, tBTA_HH_DEV_DSCP_INFO dscp_info)
+{
+ tBTA_HH_MAINT_DEV *p_buf;
+ UINT16 len = sizeof(tBTA_HH_MAINT_DEV) + dscp_info.descriptor.dl_len;
+
+ p_buf = (tBTA_HH_MAINT_DEV *)GKI_getbuf(len);
+
+ if (p_buf != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
+
+ p_buf->hdr.event = BTA_HH_API_MAINT_DEV_EVT;
+ p_buf->sub_event = BTA_HH_ADD_DEV_EVT;
+ p_buf->hdr.layer_specific = BTA_HH_INVALID_HANDLE;
+
+ p_buf->attr_mask = (UINT16) attr_mask;
+ p_buf->sub_class = sub_class;
+ p_buf->app_id = app_id;
+ bdcpy(p_buf->bda, bda);
+
+ memcpy(&p_buf->dscp_info, &dscp_info, sizeof(tBTA_HH_DEV_DSCP_INFO));
+ if ( dscp_info.descriptor.dl_len != 0 && dscp_info.descriptor.dsc_list)
+ {
+ p_buf->dscp_info.descriptor.dl_len = dscp_info.descriptor.dl_len;
+ p_buf->dscp_info.descriptor.dsc_list = (UINT8 *)(p_buf + 1);
+ memcpy(p_buf->dscp_info.descriptor.dsc_list, dscp_info.descriptor.dsc_list, dscp_info.descriptor.dl_len);
+ }
+ else
+ {
+ p_buf->dscp_info.descriptor.dsc_list = NULL;
+ p_buf->dscp_info.descriptor.dl_len = 0;
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_HhRemoveDev
+**
+** Description Remove a device from the HID host devices list.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhRemoveDev(UINT8 dev_handle )
+{
+ tBTA_HH_MAINT_DEV *p_buf;
+
+ p_buf = (tBTA_HH_MAINT_DEV *)GKI_getbuf((UINT16)sizeof(tBTA_HH_MAINT_DEV));
+
+ if (p_buf != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
+
+ p_buf->hdr.event = BTA_HH_API_MAINT_DEV_EVT;
+ p_buf->sub_event = BTA_HH_RMV_DEV_EVT;
+ p_buf->hdr.layer_specific = (UINT16) dev_handle;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************/
+/* Utility Function */
+/*******************************************************************************/
+
+/*******************************************************************************
+**
+** Function BTA_HhParseBootRpt
+**
+** Description This utility function parse a boot mode report.
+** For keyboard report, report data will carry the keycode max
+** up to 6 key press in one report. Application need to convert
+** the keycode into keypress character according to keyboard
+** language.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
+ UINT16 report_len)
+{
+ p_data->dev_type = BTA_HH_DEVT_UNKNOWN;
+
+ if (p_report)
+ {
+ /* first byte is report ID */
+ switch (p_report[0])
+ {
+ case BTA_HH_KEYBD_RPT_ID: /* key board report ID */
+ p_data->dev_type = p_report[0];
+ bta_hh_parse_keybd_rpt(p_data, p_report + 1, (UINT16)(report_len -1));
+ break;
+
+ case BTA_HH_MOUSE_RPT_ID: /* mouse report ID */
+ p_data->dev_type = p_report[0];
+ bta_hh_parse_mice_rpt(p_data, p_report + 1, (UINT16)(report_len - 1));
+ break;
+
+ default:
+ APPL_TRACE_DEBUG1("Unknown boot report: %d", p_report[0]);;
+ break;
+ }
+ }
+
+ return;
+}
+
+#endif /* BTA_HH_INCLUDED */
diff --git a/bta/hh/bta_hh_cfg.c b/bta/hh/bta_hh_cfg.c
new file mode 100644
index 0000000..62a07ad
--- /dev/null
+++ b/bta/hh/bta_hh_cfg.c
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains compile-time configurable constants for the BTA Hid
+ * Host.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "bta_hh_api.h"
+
+/* max number of device types supported by BTA */
+#define BTA_HH_MAX_DEVT_SPT 7
+
+/* size of database for service discovery */
+#ifndef BTA_HH_DISC_BUF_SIZE
+#define BTA_HH_DISC_BUF_SIZE GKI_MAX_BUF_SIZE
+#endif
+
+/* application ID(none-zero) for each type of device */
+#define BTA_HH_APP_ID_MI 1
+#define BTA_HH_APP_ID_KB 2
+#define BTA_HH_APP_ID_RMC 3
+#define BTA_HH_APP_ID_3DSG 4
+
+
+/* The type of devices supported by BTA HH and corresponding application ID */
+tBTA_HH_SPT_TOD p_devt_list[BTA_HH_MAX_DEVT_SPT] =
+{
+ {BTA_HH_DEVT_MIC, BTA_HH_APP_ID_MI},
+ {BTA_HH_DEVT_KBD, BTA_HH_APP_ID_KB},
+ {BTA_HH_DEVT_KBD|BTA_HH_DEVT_MIC, BTA_HH_APP_ID_KB},
+ {BTA_HH_DEVT_RMC, BTA_HH_APP_ID_RMC},
+ {BTA_HH_DEVT_RMC | BTA_HH_DEVT_KBD, BTA_HH_APP_ID_RMC},
+ {BTA_HH_DEVT_MIC | BTA_HH_DEVT_DGT, BTA_HH_APP_ID_MI},
+ {BTA_HH_DEVT_UNKNOWN, BTA_HH_APP_ID_3DSG}
+};
+
+
+const tBTA_HH_CFG bta_hh_cfg =
+{
+ BTA_HH_MAX_DEVT_SPT, /* number of supported type of devices */
+ p_devt_list, /* ToD & AppID list */
+ BTA_HH_DISC_BUF_SIZE /* HH SDP discovery database size */
+};
+
+
+tBTA_HH_CFG *p_bta_hh_cfg = (tBTA_HH_CFG *)&bta_hh_cfg;
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
new file mode 100644
index 0000000..f3a8e54
--- /dev/null
+++ b/bta/hh/bta_hh_int.h
@@ -0,0 +1,248 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains BTA HID Host internal definitions
+ *
+ ******************************************************************************/
+
+#ifndef BTA_HH_INT_H
+#define BTA_HH_INT_H
+
+#include "bta_sys.h"
+#include "bd.h"
+#include "utl.h"
+#include "bta_hh_api.h"
+
+/* can be moved to bta_api.h */
+#define BTA_HH_MAX_RPT_CHARS 8
+
+
+/* state machine events, these events are handled by the state machine */
+enum
+{
+ BTA_HH_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HH),
+ BTA_HH_API_CLOSE_EVT,
+ BTA_HH_INT_OPEN_EVT,
+ BTA_HH_INT_CLOSE_EVT,
+ BTA_HH_INT_DATA_EVT,
+ BTA_HH_INT_CTRL_DATA,
+ BTA_HH_INT_HANDSK_EVT,
+ BTA_HH_SDP_CMPL_EVT,
+ BTA_HH_API_WRITE_DEV_EVT,
+ BTA_HH_API_GET_DSCP_EVT,
+ BTA_HH_API_MAINT_DEV_EVT,
+ BTA_HH_OPEN_CMPL_EVT,
+
+ /* not handled by execute state machine */
+ BTA_HH_API_ENABLE_EVT,
+ BTA_HH_API_DISABLE_EVT,
+ BTA_HH_DISC_CMPL_EVT
+};
+typedef UINT16 tBTA_HH_INT_EVT; /* HID host internal events */
+
+#define BTA_HH_INVALID_EVT (BTA_HH_DISC_CMPL_EVT + 1)
+
+/* event used to map between BTE event and BTA event */
+#define BTA_HH_FST_TRANS_CB_EVT BTA_HH_GET_RPT_EVT
+#define BTA_HH_FST_BTE_TRANS_EVT HID_TRANS_GET_REPORT
+
+/* sub event code used for device maintainence API call */
+#define BTA_HH_ADD_DEV 0
+#define BTA_HH_REMOVE_DEV 1
+
+/* state machine states */
+enum
+{
+ BTA_HH_NULL_ST,
+ BTA_HH_IDLE_ST,
+ BTA_HH_W4_CONN_ST,
+ BTA_HH_CONN_ST
+};
+typedef UINT8 tBTA_HH_STATE;
+
+/* data structure used to send a command/data to HID device */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 t_type;
+ UINT8 param;
+ UINT8 rpt_id;
+ UINT16 data;
+ BT_HDR *p_data;
+}tBTA_HH_CMD_DATA;
+
+/* data type for BTA_HH_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 sec_mask;
+ UINT8 service_name[BTA_SERVICE_NAME_LEN+1];
+ tBTA_HH_CBACK *p_cback;
+} tBTA_HH_API_ENABLE;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ UINT8 sec_mask;
+ tBTA_HH_PROTO_MODE mode;
+}tBTA_HH_API_CONN;
+
+/* internal event data from BTE HID callback */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT32 data;
+ BT_HDR *p_data;
+}tBTA_HH_CBACK_DATA;
+
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bda;
+ UINT16 attr_mask;
+ UINT16 sub_event;
+ UINT8 sub_class;
+ UINT8 app_id;
+ tBTA_HH_DEV_DSCP_INFO dscp_info;
+}tBTA_HH_MAINT_DEV;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_HH_API_ENABLE api_enable;
+ tBTA_HH_API_CONN api_conn;
+ tBTA_HH_CMD_DATA api_sndcmd;
+ tBTA_HH_CBACK_DATA hid_cback;
+ tBTA_HH_STATUS status;
+ tBTA_HH_MAINT_DEV api_maintdev;
+} tBTA_HH_DATA;
+
+/* device control block */
+typedef struct
+{
+ tBTA_HH_DEV_DSCP_INFO dscp_info; /* report descriptor and DI information */
+ BD_ADDR addr; /* BD-Addr of the HID device */
+ UINT16 attr_mask; /* attribute mask */
+ UINT16 w4_evt; /* W4_handshake event name */
+ UINT8 index; /* index number referenced to handle index */
+ UINT8 sub_class; /* Cod sub class */
+ UINT8 sec_mask; /* security mask */
+ UINT8 app_id; /* application ID for this connection */
+ UINT8 hid_handle; /* device handle */
+ BOOLEAN vp; /* virtually unplug flag */
+ BOOLEAN in_use; /* control block currently in use */
+ BOOLEAN incoming_conn; /* is incoming connection? */
+ BOOLEAN opened; /* TRUE if device successfully opened HID connection */
+ tBTA_HH_PROTO_MODE mode; /* protocol mode */
+ tBTA_HH_STATE state; /* CB state */
+} tBTA_HH_DEV_CB;
+
+/* key board parsing control block */
+typedef struct
+{
+ BOOLEAN mod_key[4]; /* ctrl, shift(upper), Alt, GUI */
+ BOOLEAN num_lock;
+ BOOLEAN caps_lock;
+ UINT8 last_report[BTA_HH_MAX_RPT_CHARS];
+} tBTA_HH_KB_CB;
+
+/******************************************************************************
+** Main Control Block
+*******************************************************************************/
+typedef struct
+{
+ tBTA_HH_KB_CB kb_cb; /* key board control block,
+ suppose BTA will connect
+ to only one keyboard at
+ the same time */
+ tBTA_HH_DEV_CB kdev[BTA_HH_MAX_KNOWN]; /* device control block */
+ tBTA_HH_DEV_CB* p_cur; /* current device control
+ block idx, used in sdp */
+ UINT8 cb_index[BTA_HH_MAX_KNOWN]; /* maintain a CB index
+ map to dev handle */
+ tBTA_HH_CBACK *p_cback; /* Application callbacks */
+ tSDP_DISCOVERY_DB* p_disc_db;
+ UINT8 trace_level; /* tracing level */
+ UINT8 cnt_num; /* connected device number */
+ BOOLEAN w4_disable; /* w4 disable flag */
+}
+tBTA_HH_CB;
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_HH_CB bta_hh_cb;
+#else
+extern tBTA_HH_CB *bta_hh_cb_ptr;
+#define bta_hh_cb (*bta_hh_cb_ptr)
+#endif
+
+/* from bta_hh_cfg.c */
+extern tBTA_HH_CFG *p_bta_hh_cfg;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg);
+extern void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event,
+ tBTA_HH_DATA *p_data);
+
+/* action functions */
+extern void bta_hh_api_disc_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_close_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data);
+extern void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data);
+extern void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_get_dscp_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+
+/* utility functions */
+extern UINT8 bta_hh_find_cb(BD_ADDR bda);
+extern void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data,
+ UINT8 *p_report, UINT16 report_len);
+extern void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_kb_data,
+ UINT8 *p_report, UINT16 report_len);
+extern BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb,UINT8 sub_class);
+extern void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb);
+
+extern void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
+ UINT16 attr_mask,
+ tHID_DEV_DSCP_INFO *p_dscp_info,
+ UINT8 sub_class, UINT16 max_latency, UINT16 min_tout, UINT8 app_id);
+extern void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
+ UINT16 version);
+
+/* action functions used outside state machine */
+extern void bta_hh_api_enable(tBTA_HH_DATA *p_data);
+extern void bta_hh_api_disable(void);
+extern void bta_hh_disc_cmpl(void);
+
+
+#if BTA_HH_DEBUG
+extern void bta_hh_trace_dev_db(void);
+#endif
+
+#endif
+
diff --git a/bta/hh/bta_hh_main.c b/bta/hh/bta_hh_main.c
new file mode 100644
index 0000000..a1d0ad2
--- /dev/null
+++ b/bta/hh/bta_hh_main.c
@@ -0,0 +1,441 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the HID host main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_hh_api.h"
+#include "bta_hh_int.h"
+#include "gki.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_HH_API_DISC_ACT, /* HID host process API close action */
+ BTA_HH_OPEN_ACT, /* HID host process BTA_HH_EVT_OPEN */
+ BTA_HH_CLOSE_ACT, /* HID host process BTA_HH_EVT_CLOSE */
+ BTA_HH_DATA_ACT, /* HID host receive data report */
+ BTA_HH_CTRL_DAT_ACT,
+ BTA_HH_HANDSK_ACT,
+ BTA_HH_START_SDP, /* HID host inquery */
+ BTA_HH_SDP_CMPL,
+ BTA_HH_WRITE_DEV_ACT,
+ BTA_HH_GET_DSCP_ACT,
+ BTA_HH_MAINT_DEV_ACT,
+ BTA_HH_OPEN_CMPL_ACT,
+ BTA_HH_NUM_ACTIONS
+};
+
+#define BTA_HH_IGNORE BTA_HH_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tBTA_HH_ACTION)(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+
+/* action functions */
+const tBTA_HH_ACTION bta_hh_action[] =
+{
+ bta_hh_api_disc_act,
+ bta_hh_open_act,
+ bta_hh_close_act,
+ bta_hh_data_act,
+ bta_hh_ctrl_dat_act,
+ bta_hh_handsk_act,
+ bta_hh_start_sdp,
+ bta_hh_sdp_cmpl,
+ bta_hh_write_dev_act,
+ bta_hh_get_dscp_act,
+ bta_hh_maint_dev_act,
+ bta_hh_open_cmpl_act
+};
+
+/* state table information */
+#define BTA_HH_ACTION 0 /* position of action */
+#define BTA_HH_NEXT_STATE 1 /* position of next state */
+#define BTA_HH_NUM_COLS 2 /* number of columns */
+
+/* state table for idle state */
+const UINT8 bta_hh_st_idle[][BTA_HH_NUM_COLS] =
+{
+/* Event Action Next state */
+/* BTA_HH_API_OPEN_EVT */ {BTA_HH_START_SDP, BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_CLOSE_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
+/* BTA_HH_INT_OPEN_EVT */ {BTA_HH_OPEN_ACT, BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CLOSE_EVT */ {BTA_HH_CLOSE_ACT, BTA_HH_IDLE_ST },
+/* BTA_HH_INT_DATA_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
+/* BTA_HH_INT_CTRL_DATA */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
+/* BTA_HH_INT_HANDSK_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
+/* BTA_HH_SDP_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
+/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
+/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
+/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST },
+/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST }
+
+};
+
+
+const UINT8 bta_hh_st_w4_conn[][BTA_HH_NUM_COLS] =
+{
+/* Event Action Next state */
+/* BTA_HH_API_OPEN_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_CLOSE_EVT */ {BTA_HH_IGNORE, BTA_HH_IDLE_ST },
+/* BTA_HH_INT_OPEN_EVT */ {BTA_HH_OPEN_ACT, BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CLOSE_EVT */ {BTA_HH_CLOSE_ACT, BTA_HH_IDLE_ST },
+/* BTA_HH_INT_DATA_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CTRL_DATA */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_HANDSK_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
+/* BTA_HH_SDP_CMPL_EVT */ {BTA_HH_SDP_CMPL, BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_IGNORE , BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_IGNORE, BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST },
+/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST }
+};
+
+
+const UINT8 bta_hh_st_connected[][BTA_HH_NUM_COLS] =
+{
+/* Event Action Next state */
+/* BTA_HH_API_OPEN_EVT */ {BTA_HH_IGNORE, BTA_HH_CONN_ST },
+/* BTA_HH_API_CLOSE_EVT */ {BTA_HH_API_DISC_ACT, BTA_HH_CONN_ST },
+/* BTA_HH_INT_OPEN_EVT */ {BTA_HH_OPEN_ACT, BTA_HH_CONN_ST },
+/* BTA_HH_INT_CLOSE_EVT */ {BTA_HH_CLOSE_ACT, BTA_HH_IDLE_ST },
+/* BTA_HH_INT_DATA_EVT */ {BTA_HH_DATA_ACT, BTA_HH_CONN_ST },
+/* BTA_HH_INT_CTRL_DATA */ {BTA_HH_CTRL_DAT_ACT, BTA_HH_CONN_ST },
+/* BTA_HH_INT_HANDSK_EVT */ {BTA_HH_HANDSK_ACT, BTA_HH_CONN_ST },
+/* BTA_HH_SDP_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_CONN_ST },
+/* BTA_HH_API_WRITE_DEV_EVT */ {BTA_HH_WRITE_DEV_ACT, BTA_HH_CONN_ST },
+/* BTA_HH_API_GET_DSCP_EVT */ {BTA_HH_GET_DSCP_ACT, BTA_HH_CONN_ST },
+/* BTA_HH_API_MAINT_DEV_EVT */ {BTA_HH_MAINT_DEV_ACT, BTA_HH_CONN_ST },
+/* BTA_HH_OPEN_CMPL_EVT */ {BTA_HH_IGNORE, BTA_HH_CONN_ST }
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_HH_ST_TBL)[BTA_HH_NUM_COLS];
+
+/* state table */
+const tBTA_HH_ST_TBL bta_hh_st_tbl[] =
+{
+ bta_hh_st_idle,
+ bta_hh_st_w4_conn,
+ bta_hh_st_connected
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_HH_CB bta_hh_cb;
+#endif
+/*****************************************************************************
+** Static functions
+*****************************************************************************/
+#if BTA_HH_DEBUG == TRUE
+static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code);
+static char *bta_hh_state_code(tBTA_HH_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_hh_sm_execute
+**
+** Description State machine event handling function for HID Host
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA * p_data)
+{
+ tBTA_HH_ST_TBL state_table;
+ UINT8 action;
+ tBTA_HH cback_data;
+ tBTA_HH_EVT cback_event = 0;
+#if BTA_HH_DEBUG == TRUE
+ tBTA_HH_STATE in_state ;
+ UINT16 debug_event = event;
+#endif
+
+ memset(&cback_data, 0, sizeof(tBTA_HH));
+
+ /* handle exception, no valid control block was found */
+ if (!p_cb)
+ {
+ /* BTA HH enabled already? otherwise ignore the event although it's bad*/
+ if (bta_hh_cb.p_cback != NULL)
+ {
+ switch (event)
+ {
+ /* no control block available for new connection */
+ case BTA_HH_API_OPEN_EVT:
+ cback_event = BTA_HH_OPEN_EVT;
+ /* build cback data */
+ bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr);
+ cback_data.conn.status = BTA_HH_ERR_DB_FULL;
+ cback_data.conn.handle = BTA_HH_INVALID_HANDLE;
+ break;
+ /* DB full, BTA_HhAddDev */
+ case BTA_HH_API_MAINT_DEV_EVT:
+ cback_event = p_data->api_maintdev.sub_event;
+
+ if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT)
+ {
+ bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda);
+ cback_data.dev_info.status = BTA_HH_ERR_DB_FULL;
+ cback_data.dev_info.handle = BTA_HH_INVALID_HANDLE;
+ }
+ else
+ {
+ cback_data.dev_info.status = BTA_HH_ERR_HDL;
+ cback_data.dev_info.handle = (UINT8)p_data->api_maintdev.hdr.layer_specific;
+ }
+ break;
+ case BTA_HH_API_WRITE_DEV_EVT:
+ cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
+ BTA_HH_FST_TRANS_CB_EVT;
+ if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL ||
+ p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT ||
+ p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE)
+ {
+ cback_data.dev_status.status = BTA_HH_ERR_HDL;
+ cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+ }
+ else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA &&
+ p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
+ {
+ cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+ cback_data.hs_data.status = BTA_HH_ERR_HDL;
+ /* hs_data.rsp_data will be all zero, which is not valid value */
+ }
+ break;
+
+ case BTA_HH_API_CLOSE_EVT:
+ cback_event = BTA_HH_CLOSE_EVT;
+
+ cback_data.dev_status.status = BTA_HH_ERR_HDL;
+ cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+ break;
+
+ default:
+ /* invalid handle, call bad API event */
+ APPL_TRACE_ERROR1("wrong device handle: [%d]", p_data->hdr.layer_specific);
+ break;
+ }
+ if (cback_event)
+ (* bta_hh_cb.p_cback)(cback_event, &cback_data);
+ }
+ }
+ /* corresponding CB is found, go to state machine */
+ else
+ {
+#if BTA_HH_DEBUG == TRUE
+ in_state = p_cb->state;
+ APPL_TRACE_EVENT3("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]",
+ in_state, bta_hh_state_code(in_state),
+ bta_hh_evt_code(debug_event));
+#endif
+
+ state_table = bta_hh_st_tbl[p_cb->state - 1];
+
+ event &= 0xff;
+
+ p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ;
+
+ if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE)
+ {
+ (*bta_hh_action[action])(p_cb, p_data);
+ }
+
+#if BTA_HH_DEBUG == TRUE
+ if (in_state != p_cb->state)
+ {
+ APPL_TRACE_DEBUG3("HH State Change: [%s] -> [%s] after Event [%s]",
+ bta_hh_state_code(in_state),
+ bta_hh_state_code(p_cb->state),
+ bta_hh_evt_code(debug_event));
+ }
+#endif
+ }
+
+ return;
+}
+/*******************************************************************************
+**
+** Function bta_hh_hdl_event
+**
+** Description HID host main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
+{
+ UINT8 index = BTA_HH_MAX_KNOWN;
+ tBTA_HH_DEV_CB *p_cb = NULL;
+
+ switch (p_msg->event)
+ {
+ case BTA_HH_API_ENABLE_EVT:
+ bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
+ break;
+
+ case BTA_HH_API_DISABLE_EVT:
+ bta_hh_api_disable();
+ break;
+
+ case BTA_HH_DISC_CMPL_EVT: /* disable complete */
+ bta_hh_disc_cmpl();
+ break;
+
+ default:
+ /* all events processed in state machine need to find corresponding
+ CB before proceed */
+ if (p_msg->event == BTA_HH_API_OPEN_EVT)
+ {
+ index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr);
+ }
+ else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT)
+ {
+ /* if add device */
+ if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT)
+ {
+ index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda);
+ }
+ else /* else remove device by handle */
+ {
+ index = bta_hh_cb.cb_index[p_msg->layer_specific];
+// btla-specific ++
+ /* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
+ * then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
+ * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
+ * So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
+ * force the index to be MAX_KNOWN
+ */
+ if (bta_hh_cb.kdev[index].in_use == FALSE) {
+ index = BTA_HH_MAX_KNOWN;
+ }
+// btla-specific --
+ }
+ }
+ else if (p_msg->layer_specific < BTA_HH_MAX_KNOWN )
+ index = bta_hh_cb.cb_index[p_msg->layer_specific];
+
+ if (index != BTA_HH_MAX_KNOWN)
+ p_cb = &bta_hh_cb.kdev[index];
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG2("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index);
+#endif
+ bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg);
+ }
+ return (TRUE);
+}
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_HH_DEBUG
+/*******************************************************************************
+**
+** Function bta_hh_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_HH_API_DISABLE_EVT:
+ return "BTA_HH_API_DISABLE_EVT";
+ case BTA_HH_API_ENABLE_EVT:
+ return "BTA_HH_API_ENABLE_EVT";
+ case BTA_HH_API_OPEN_EVT:
+ return "BTA_HH_API_OPEN_EVT";
+ case BTA_HH_API_CLOSE_EVT:
+ return "BTA_HH_API_CLOSE_EVT";
+ case BTA_HH_INT_OPEN_EVT:
+ return "BTA_HH_INT_OPEN_EVT";
+ case BTA_HH_INT_CLOSE_EVT:
+ return "BTA_HH_INT_CLOSE_EVT";
+ case BTA_HH_INT_HANDSK_EVT:
+ return "BTA_HH_INT_HANDSK_EVT";
+ case BTA_HH_INT_DATA_EVT:
+ return "BTA_HH_INT_DATA_EVT";
+ case BTA_HH_INT_CTRL_DATA:
+ return "BTA_HH_INT_CTRL_DATA";
+ case BTA_HH_API_WRITE_DEV_EVT:
+ return "BTA_HH_API_WRITE_DEV_EVT";
+ case BTA_HH_SDP_CMPL_EVT:
+ return "BTA_HH_SDP_CMPL_EVT";
+ case BTA_HH_DISC_CMPL_EVT:
+ return "BTA_HH_DISC_CMPL_EVT";
+ case BTA_HH_API_MAINT_DEV_EVT:
+ return "BTA_HH_API_MAINT_DEV_EVT";
+ case BTA_HH_API_GET_DSCP_EVT:
+ return "BTA_HH_API_GET_DSCP_EVT";
+ case BTA_HH_OPEN_CMPL_EVT:
+ return "BTA_HH_OPEN_CMPL_EVT";
+ default:
+ return "unknown HID Host event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_state_code
+**
+** Description get string representation of HID host state code.
+**
+** Returns void
+**
+*******************************************************************************/
+static char *bta_hh_state_code(tBTA_HH_STATE state_code)
+{
+ switch (state_code)
+ {
+ case BTA_HH_NULL_ST:
+ return"BTA_HH_NULL_ST";
+ case BTA_HH_IDLE_ST:
+ return "BTA_HH_IDLE_ST";
+ case BTA_HH_W4_CONN_ST:
+ return "BTA_HH_W4_CONN_ST";
+ case BTA_HH_CONN_ST:
+ return "BTA_HH_CONN_ST";
+ default:
+ return "unknown HID Host state";
+ }
+}
+
+#endif /* Debug Functions */
+
+#endif /* BTA_HH_INCLUDED */
diff --git a/bta/hh/bta_hh_utils.c b/bta/hh/bta_hh_utils.c
new file mode 100644
index 0000000..4349282
--- /dev/null
+++ b/bta/hh/bta_hh_utils.c
@@ -0,0 +1,417 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+
+#include "bta_hh_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+#define BTA_HH_KB_CTRL_MASK 0x11
+#define BTA_HH_KB_SHIFT_MASK 0x22
+#define BTA_HH_KB_ALT_MASK 0x44
+#define BTA_HH_KB_GUI_MASK 0x88
+
+#define BTA_HH_KB_CAPS_LOCK 0x39 /* caps lock */
+#define BTA_HH_KB_NUM_LOCK 0x53 /* num lock */
+
+
+#define BTA_HH_MAX_RPT_CHARS 8
+
+static const UINT8 bta_hh_mod_key_mask[BTA_HH_MOD_MAX_KEY] =
+{
+ BTA_HH_KB_CTRL_MASK,
+ BTA_HH_KB_SHIFT_MASK,
+ BTA_HH_KB_ALT_MASK,
+ BTA_HH_KB_GUI_MASK
+};
+
+
+/*******************************************************************************
+**
+** Function bta_hh_find_cb
+**
+** Description Find best available control block according to BD address.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+UINT8 bta_hh_find_cb(BD_ADDR bda)
+{
+ UINT8 xx;
+
+ /* See how many active devices there are. */
+ for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+ {
+ /* check if any active/known devices is a match */
+ if ((!bdcmp (bda, bta_hh_cb.kdev[xx].addr) &&
+ bdcmp(bda, bd_addr_null) != 0) )
+ {
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG2("found kdev_cb[%d] hid_handle = %d ", xx,
+ bta_hh_cb.kdev[xx].hid_handle)
+#endif
+ return xx;
+ }
+#if BTA_HH_DEBUG
+ else
+ APPL_TRACE_DEBUG4("in_use ? [%d] kdev[%d].hid_handle = %d state = [%d]",
+ bta_hh_cb.kdev[xx].in_use, xx,
+ bta_hh_cb.kdev[xx].hid_handle,
+ bta_hh_cb.kdev[xx].state);
+#endif
+ }
+
+ /* if no active device match, find a spot for it */
+ for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+ {
+ if (!bta_hh_cb.kdev[xx].in_use)
+ {
+ bdcpy(bta_hh_cb.kdev[xx].addr, bda);
+ break;
+ }
+ }
+ /* If device list full, report BTA_HH_MAX_KNOWN */
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG2("bta_hh_find_cb:: index = %d while max = %d",
+ xx, BTA_HH_MAX_KNOWN);
+#endif
+
+ return xx;
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_clean_up_kdev
+**
+** Description Clean up device control block when device is removed from
+** manitainace list, and update control block index map.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb)
+{
+ UINT8 index;
+
+ if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE )
+ bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_MAX_KNOWN;
+
+ /* reset device control block */
+ index = p_cb->index; /* Preserve index for this control block */
+
+ /* Free buffer for report descriptor info */
+ utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
+
+ memset(p_cb, 0, sizeof (tBTA_HH_DEV_CB)); /* Reset control block */
+
+ p_cb->index = index; /* Restore index for this control block */
+ p_cb->state = BTA_HH_IDLE_ST;
+ p_cb->hid_handle = BTA_HH_INVALID_HANDLE;
+
+}
+/*******************************************************************************
+**
+** Function bta_hh_update_di_info
+**
+** Description Maintain a known device list for BTA HH.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
+ UINT16 version)
+{
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG3("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x",
+ vendor_id, product_id, version);
+#endif
+ p_cb->dscp_info.vendor_id = vendor_id;
+ p_cb->dscp_info.product_id = product_id;
+ p_cb->dscp_info.version = version;
+}
+/*******************************************************************************
+**
+** Function bta_hh_add_device_to_list
+**
+** Description Maintain a known device list for BTA HH.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
+ UINT16 attr_mask,
+ tHID_DEV_DSCP_INFO *p_dscp_info,
+ UINT8 sub_class,
+ UINT16 ssr_max_latency,
+ UINT16 ssr_min_tout,
+ UINT8 app_id)
+{
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1("subclass = 0x%2x", sub_class);
+#endif
+
+ p_cb->hid_handle = handle;
+ p_cb->in_use = TRUE;
+ p_cb->attr_mask = attr_mask;
+
+ p_cb->sub_class = sub_class;
+ p_cb->app_id = app_id;
+
+ if (ssr_max_latency == HID_SSR_PARAM_INVALID)
+ p_cb->dscp_info.ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
+ else
+ p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
+
+ if (ssr_min_tout == HID_SSR_PARAM_INVALID)
+ p_cb->dscp_info.ssr_min_tout = BTA_HH_SSR_MIN_TOUT_DEF;
+ else
+ p_cb->dscp_info.ssr_min_tout = ssr_min_tout;
+
+ /* store report descriptor info */
+ if ( p_dscp_info)
+ {
+ utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
+
+ if (p_dscp_info->dl_len &&
+ (p_cb->dscp_info.descriptor.dsc_list =
+ (UINT8 *)GKI_getbuf(p_dscp_info->dl_len)) != NULL)
+ {
+ p_cb->dscp_info.descriptor.dl_len = p_dscp_info->dl_len;
+ memcpy(p_cb->dscp_info.descriptor.dsc_list, p_dscp_info->dsc_list,
+ p_dscp_info->dl_len);
+ }
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_tod_spt
+**
+** Description Check to see if this type of device is supported
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb,UINT8 sub_class)
+{
+ UINT8 xx;
+ UINT8 cod = (sub_class >> 2); /* lower two bits are reserved */
+
+ for (xx = 0 ; xx < p_bta_hh_cfg->max_devt_spt; xx ++)
+ {
+ if (cod == (UINT8) p_bta_hh_cfg->p_devt_list[xx].tod)
+ {
+ p_cb->app_id = p_bta_hh_cfg->p_devt_list[xx].app_id;
+#if BTA_HH_DEBUG
+ APPL_TRACE_EVENT1("bta_hh_tod_spt sub_class:0x%x supported", sub_class);
+#endif
+ return TRUE;
+ }
+ }
+#if BTA_HH_DEBUG
+ APPL_TRACE_EVENT1("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
+#endif
+ return FALSE;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hh_parse_keybd_rpt
+**
+** Description This utility function parse a boot mode keyboard report.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data, UINT8 *p_report,
+ UINT16 report_len)
+{
+ tBTA_HH_KB_CB *p_kb = &bta_hh_cb.kb_cb;
+ tBTA_HH_KEYBD_RPT *p_data = &p_kb_data->data_rpt.keybd_rpt;
+
+ UINT8 this_char, ctl_shift;
+ UINT16 xx, yy, key_idx = 0;
+ UINT8 this_report[BTA_HH_MAX_RPT_CHARS];
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG2("bta_hh_parse_keybd_rpt: (report=%p, report_len=%d) called",
+ p_report, report_len);
+#endif
+
+ if (report_len < 2)
+ return;
+
+ ctl_shift = *p_report++;
+ report_len--;
+
+ if (report_len > BTA_HH_MAX_RPT_CHARS)
+ report_len = BTA_HH_MAX_RPT_CHARS;
+
+ memset (this_report, 0, BTA_HH_MAX_RPT_CHARS);
+ memset (p_data, 0, sizeof(tBTA_HH_KEYBD_RPT));
+ memcpy (this_report, p_report, report_len);
+
+ /* Take care of shift, control, GUI and alt, modifier keys */
+ for (xx = 0; xx < BTA_HH_MOD_MAX_KEY; xx ++ )
+ {
+ if (ctl_shift & bta_hh_mod_key_mask[xx])
+ {
+ APPL_TRACE_DEBUG1("Mod Key[%02x] pressed", bta_hh_mod_key_mask[xx] );
+ p_kb->mod_key[xx] = TRUE;
+ }
+ else if (p_kb->mod_key[xx])
+ {
+ p_kb->mod_key[xx] = FALSE;
+ }
+ /* control key flag is set */
+ p_data->mod_key[xx] = p_kb->mod_key[xx];
+ }
+
+ /***************************************************************************/
+ /* First step is to remove all characters we saw in the last report */
+ /***************************************************************************/
+ for (xx = 0; xx < report_len; xx++)
+ {
+ for (yy = 0; yy < BTA_HH_MAX_RPT_CHARS; yy++)
+ {
+ if (this_report[xx] == p_kb->last_report[yy])
+ {
+ this_report[xx] = 0;
+ }
+ }
+ }
+ /***************************************************************************/
+ /* Now, process all the characters in the report, up to 6 keycodes */
+ /***************************************************************************/
+ for (xx = 0; xx < report_len; xx++)
+ {
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1("this_char = %02x", this_report[xx]);
+#endif
+ if ((this_char = this_report[xx]) == 0)
+ continue;
+ /* take the key code as the report data */
+ if (this_report[xx] == BTA_HH_KB_CAPS_LOCK)
+ p_kb->caps_lock = p_kb->caps_lock ? FALSE : TRUE;
+ else if (this_report[xx] == BTA_HH_KB_NUM_LOCK)
+ p_kb->num_lock = p_kb->num_lock ? FALSE : TRUE;
+ else
+ p_data->this_char[key_idx ++] = this_char;
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1("found keycode %02x ", this_report[xx]);
+#endif
+ p_data->caps_lock = p_kb->caps_lock;
+ p_kb->num_lock = p_kb->num_lock;
+ }
+
+ memset (p_kb->last_report, 0, BTA_HH_MAX_RPT_CHARS);
+ memcpy (p_kb->last_report, p_report, report_len);
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_hh_parse_mice_rpt
+**
+** Description This utility function parse a boot mode mouse report.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_mice_data, UINT8 *p_report,
+ UINT16 report_len)
+{
+ tBTA_HH_MICE_RPT *p_data = &p_mice_data->data_rpt.mice_rpt;
+#if BTA_HH_DEBUG
+ UINT8 xx;
+
+ APPL_TRACE_DEBUG2("bta_hh_parse_mice_rpt: bta_keybd_rpt_rcvd(report=%p, \
+ report_len=%d) called", p_report, report_len);
+#endif
+
+ if (report_len < 3)
+ return;
+
+ if (report_len > BTA_HH_MAX_RPT_CHARS)
+ report_len = BTA_HH_MAX_RPT_CHARS;
+
+#if BTA_HH_DEBUG
+ for (xx = 0; xx < report_len; xx++)
+ {
+ APPL_TRACE_DEBUG1("this_char = %02x", p_report[xx]);
+ }
+#endif
+
+ /* only first bytes lower 3 bits valid */
+ p_data->mouse_button = (p_report[0] & 0x07);
+
+ /* x displacement */
+ p_data->delta_x = p_report[1];
+
+ /* y displacement */
+ p_data->delta_y = p_report[2];
+
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1("mice button: 0x%2x", p_data->mouse_button);
+ APPL_TRACE_DEBUG2("mice move: x = %d y = %d", p_data->delta_x,
+ p_data->delta_y );
+#endif
+
+ return;
+
+}
+
+#if BTA_HH_DEBUG
+/*******************************************************************************
+**
+** Function bta_hh_trace_dev_db
+**
+** Description Check to see if this type of device is supported
+**
+** Returns
+**
+*******************************************************************************/
+void bta_hh_trace_dev_db(void)
+{
+ UINT8 xx;
+
+ APPL_TRACE_DEBUG0("bta_hh_trace_dev_db:: Device DB list********************");
+
+ for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+ {
+ APPL_TRACE_DEBUG3("kdev[%d] in_use[%d] handle[%d] ",xx,
+ bta_hh_cb.kdev[xx].in_use, bta_hh_cb.kdev[xx].hid_handle);
+
+ APPL_TRACE_DEBUG4("\t\t\t attr_mask[%04x] state [%d] sub_class[%02x] index = %d",
+ bta_hh_cb.kdev[xx].attr_mask, bta_hh_cb.kdev[xx].state,
+ bta_hh_cb.kdev[xx].sub_class, bta_hh_cb.kdev[xx].index);
+ }
+ APPL_TRACE_DEBUG0("*********************************************************");
+}
+#endif
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_act.c b/bta/hl/bta_hl_act.c
new file mode 100644
index 0000000..0f46e5e
--- /dev/null
+++ b/bta/hl/bta_hl_act.c
@@ -0,0 +1,2807 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the HeaLth device profile (HL) action functions for
+ * the state machine.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+#include "gki.h"
+#include "sdp_api.h"
+#include "bta_sys.h"
+#include "port_api.h"
+#include "sdp_api.h"
+#include "bta_hl_api.h"
+#include "bta_hl_int.h"
+#include "utl.h"
+#include "bd.h"
+#include "mca_defs.h"
+#include "mca_api.h"
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if (BTA_HL_DEBUG == TRUE && BT_TRACE_VERBOSE == TRUE)
+static char *bta_hl_mcap_evt_code(UINT8 evt_code);
+static char *bta_hl_dch_oper_code(tBTA_HL_DCH_OPER oper_code);
+static char *bta_hl_cback_evt_code(UINT8 evt_code);
+#endif
+static void bta_hl_sdp_cback(UINT8 sdp_op, UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx, UINT16 status);
+static void bta_hl_sdp_cback0(UINT16 status);
+static void bta_hl_sdp_cback1(UINT16 status);
+static void bta_hl_sdp_cback2(UINT16 status);
+static void bta_hl_sdp_cback3(UINT16 status);
+static void bta_hl_sdp_cback4(UINT16 status);
+static void bta_hl_sdp_cback5(UINT16 status);
+static void bta_hl_sdp_cback6(UINT16 status);
+
+
+static tSDP_DISC_CMPL_CB * const bta_hl_sdp_cback_arr[] = {
+ bta_hl_sdp_cback0,
+ bta_hl_sdp_cback1,
+ bta_hl_sdp_cback2,
+ bta_hl_sdp_cback3,
+ bta_hl_sdp_cback4,
+ bta_hl_sdp_cback5,
+ bta_hl_sdp_cback6
+};
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_cong_change
+**
+** Description Action routine for processing congestion change notification
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_cong_change(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_CONG_CHG *p_cong_chg = &p_data->mca_evt.mca_data.cong_chg;
+ tBTA_HL evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG2("bta_hl_dch_mca_cong_change mdl_id=%d cong=%d",
+ p_cong_chg->mdl_id,
+ p_cong_chg->cong);
+#endif
+ evt_data.dch_cong_ind.cong =
+ p_dcb->cong = p_cong_chg->cong;
+ evt_data.dch_cong_ind.mdl_handle = p_dcb->mdl_handle;
+ evt_data.dch_cong_ind.mcl_handle = p_mcb->mcl_handle;
+ evt_data.dch_cong_ind.app_handle = p_acb->app_handle;
+
+ p_acb->p_cback(BTA_HL_CONG_CHG_IND_EVT ,(tBTA_HL *) &evt_data );
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_echo_test
+**
+** Description Action routine for processing echo test request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_echo_test(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_echo_test");
+#endif
+
+ p_dcb->echo_oper = BTA_HL_ECHO_OP_CI_GET_ECHO_DATA;
+ p_dcb->cout_oper |= BTA_HL_CO_GET_ECHO_DATA_MASK;
+
+ bta_hl_co_get_echo_data(p_acb->app_id, p_mcb->mcl_handle,
+ p_dcb->p_echo_tx_pkt->len,
+ BTA_HL_GET_BUF_PTR(p_dcb->p_echo_tx_pkt),
+ BTA_HL_CI_GET_ECHO_DATA_EVT);
+
+}
+/*******************************************************************************
+**
+** Function bta_hl_dch_sdp_init
+**
+** Description Action routine for processing DCH SDP initiation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_sdp_init(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_sdp_init");
+#endif
+ if ( p_mcb->sdp_oper == BTA_HL_SDP_OP_NONE)
+ {
+ p_mcb->sdp_mdl_idx = mdl_idx;
+ if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN )
+ {
+ p_mcb->sdp_oper = BTA_HL_SDP_OP_DCH_OPEN_INIT;
+
+ }
+ else
+ {
+ p_mcb->sdp_oper = BTA_HL_SDP_OP_DCH_RECONNECT_INIT;
+ }
+
+ if (bta_hl_init_sdp(p_mcb->sdp_oper, app_idx, mcl_idx, mdl_idx) != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_ERROR0("SDP INIT failed");
+ p_mcb->sdp_oper = BTA_HL_SDP_OP_NONE;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_FAIL_EVT, p_data);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("SDP in use");
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_FAIL_EVT, p_data);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_close_echo_test
+**
+** Description Action routine for processing the closing of echo test
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_close_echo_test(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_close_echo_test");
+#endif
+
+ switch (p_dcb->echo_oper)
+ {
+ case BTA_HL_ECHO_OP_DCH_CLOSE_CFM:
+ case BTA_HL_ECHO_OP_OPEN_IND:
+ case BTA_HL_ECHO_OP_ECHO_PKT:
+ p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST;
+ break;
+ case BTA_HL_ECHO_OP_MDL_CREATE_CFM:
+ case BTA_HL_ECHO_OP_DCH_OPEN_CFM:
+ case BTA_HL_ECHO_OP_LOOP_BACK:
+ default:
+ break;
+ }
+
+ if (MCA_CloseReq((tMCA_DL) p_dcb->mdl_handle)!= MCA_SUCCESS)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_rcv_data
+**
+** Description Action routine for processing the received data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_rcv_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_rcv_data");
+#endif
+
+ if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ switch ( p_dcb->echo_oper)
+ {
+ case BTA_HL_ECHO_OP_ECHO_PKT:
+
+ if (MCA_WriteReq((tMCA_DL) p_dcb->mdl_handle, p_data->mca_rcv_data_evt.p_pkt) != MCA_SUCCESS)
+ {
+ utl_freebuf((void **) &p_data->mca_rcv_data_evt.p_pkt);
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
+ }
+ break;
+ case BTA_HL_ECHO_OP_LOOP_BACK:
+
+ p_dcb->p_echo_rx_pkt = p_data->mca_rcv_data_evt.p_pkt;
+ p_dcb->echo_oper = BTA_HL_ECHO_OP_CI_PUT_ECHO_DATA;
+ p_dcb->cout_oper |= BTA_HL_CO_PUT_ECHO_DATA_MASK;
+ p_dcb->ci_put_echo_data_status = BTA_HL_STATUS_FAIL;
+
+ bta_hl_co_put_echo_data(p_acb->app_id, p_mcb->mcl_handle,
+ p_dcb->p_echo_rx_pkt->len,
+ BTA_HL_GET_BUF_PTR(p_dcb->p_echo_rx_pkt),
+ BTA_HL_CI_PUT_ECHO_DATA_EVT);
+ break;
+ default:
+ APPL_TRACE_ERROR1("Unknonw echo_oper=%d",p_dcb->echo_oper);
+ break;
+ }
+
+ }
+ else
+ {
+ p_dcb->cout_oper |= BTA_HL_CO_PUT_RX_DATA_MASK;
+ p_dcb->p_rx_pkt = p_data->mca_rcv_data_evt.p_pkt;
+
+ bta_hl_co_put_rx_data(p_acb->app_id, p_dcb->mdl_handle,
+ p_dcb->p_rx_pkt->len,
+ BTA_HL_GET_BUF_PTR(p_dcb->p_rx_pkt),
+ BTA_HL_CI_PUT_RX_DATA_EVT);
+
+
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_ci_put_echo_data
+**
+** Description Action routine for processing the call-in of the
+** put echo data event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_ci_put_echo_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_ci_put_echo_data");
+#endif
+
+ p_dcb->cout_oper &= ~BTA_HL_CO_PUT_ECHO_DATA_MASK;
+ utl_freebuf((void **) &p_dcb->p_echo_rx_pkt);
+ p_dcb->ci_put_echo_data_status = p_data->ci_get_put_echo_data.status;
+
+ p_dcb->echo_oper = BTA_HL_ECHO_OP_DCH_CLOSE_CFM;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_ci_get_echo_data
+**
+** Description Action routine for processing the call-in of the
+** get echo data event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_ci_get_echo_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL_STATUS status;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_ci_get_echo_data");
+#endif
+
+ p_dcb->cout_oper &= ~BTA_HL_CO_GET_ECHO_DATA_MASK;
+
+ if (!p_dcb->abort_oper)
+ {
+ status = p_data->ci_get_put_echo_data.status;
+ if (status == BTA_HL_STATUS_OK)
+ {
+ p_dcb->echo_oper = BTA_HL_ECHO_OP_MDL_CREATE_CFM;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_OPEN_EVT, p_data);
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_ci_put_rx_data
+**
+** Description Action routine for processing the call-in of the
+** put rx data event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_ci_put_rx_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_ci_put_rx_data");
+#endif
+
+ p_dcb->cout_oper &= ~BTA_HL_CO_PUT_RX_DATA_MASK;
+ utl_freebuf((void **) &p_dcb->p_rx_pkt);
+ bta_hl_build_rcv_data_ind(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_dcb->mdl_handle);
+ p_acb->p_cback(BTA_HL_DCH_RCV_DATA_IND_EVT,(tBTA_HL *) &evt_data );
+ if (p_dcb->close_pending)
+ {
+ if (!p_dcb->cout_oper)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT, p_data);
+ }
+
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_ci_get_tx_data
+**
+** Description Action routine for processing the call-in of the
+** get tx data event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_ci_get_tx_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_RESULT result;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ BOOLEAN free_buf = FALSE;
+ BOOLEAN close_dch = FALSE;
+ tBTA_HL evt_data;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_ci_get_tx_data");
+#endif
+
+ p_dcb->cout_oper &= ~BTA_HL_CO_GET_TX_DATA_MASK;
+
+ if (p_dcb->close_pending)
+ {
+ status = BTA_HL_STATUS_FAIL;
+ free_buf = TRUE;
+
+ if (!p_dcb->cout_oper)
+ {
+ close_dch = TRUE;
+ }
+ }
+ else
+ {
+ if ((result = MCA_WriteReq((tMCA_DL) p_dcb->mdl_handle, p_dcb->p_tx_pkt)) != MCA_SUCCESS)
+ {
+ if (result == MCA_BUSY)
+ {
+ status = BTA_HL_STATUS_DCH_BUSY;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_FAIL;
+ }
+ free_buf = TRUE;
+ }
+ else
+ {
+ p_dcb->p_tx_pkt = NULL;
+ }
+ }
+
+ if (free_buf)
+ {
+ utl_freebuf((void **) &p_dcb->p_tx_pkt);
+ }
+
+ bta_hl_build_send_data_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_dcb->mdl_handle,
+ status);
+ p_acb->p_cback(BTA_HL_DCH_SEND_DATA_CFM_EVT,(tBTA_HL *) &evt_data );
+
+ if (close_dch)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT, p_data);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_send_data
+**
+** Description Action routine for processing api send data request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_send_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL evt_data;
+ BOOLEAN success = TRUE;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_send_data");
+#endif
+
+ if (!(p_dcb->cout_oper & BTA_HL_CO_GET_TX_DATA_MASK))
+ {
+ if ((p_dcb->p_tx_pkt = bta_hl_get_buf(p_data->api_send_data.pkt_size)) != NULL)
+ {
+ bta_hl_co_get_tx_data( p_acb->app_id,
+ p_dcb->mdl_handle,
+ p_data->api_send_data.pkt_size,
+ BTA_HL_GET_BUF_PTR(p_dcb->p_tx_pkt),
+ BTA_HL_CI_GET_TX_DATA_EVT);
+ p_dcb->cout_oper |= BTA_HL_CO_GET_TX_DATA_MASK;
+ }
+ else
+ {
+ success = FALSE;
+ }
+ }
+ else
+ {
+ success = FALSE;
+ }
+
+ if (!success)
+ {
+ bta_hl_build_send_data_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_dcb->mdl_handle,
+ BTA_HL_STATUS_FAIL);
+ p_acb->p_cback(BTA_HL_DCH_SEND_DATA_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_close_cmpl
+**
+** Description Action routine for processing the close complete event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL evt_data;
+ tBTA_HL_EVT event;
+ BOOLEAN send_evt=TRUE;
+ tBTA_HL_STATUS status;
+
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+ APPL_TRACE_DEBUG1("bta_hl_dch_close_cmpl dch oper=%s", bta_hl_dch_oper_code(p_dcb->dch_oper));
+#else
+ APPL_TRACE_DEBUG1("bta_hl_dch_close_cmpl dch oper=%d", p_dcb->dch_oper);
+#endif
+#endif
+
+ switch (p_dcb->dch_oper)
+ {
+ case BTA_HL_DCH_OP_LOCAL_OPEN:
+ case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+
+ if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK)
+ {
+ bta_hl_build_abort_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ BTA_HL_STATUS_OK);
+ event = BTA_HL_DCH_ABORT_CFM_EVT;
+ }
+ else if (p_dcb->abort_oper & BTA_HL_ABORT_REMOTE_MASK )
+ {
+ bta_hl_build_abort_ind(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle);
+ event = BTA_HL_DCH_ABORT_IND_EVT;
+ }
+ else
+ {
+ bta_hl_build_dch_open_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ BTA_HL_INVALID_MDL_HANDLE,
+ 0,0,0,0,0, BTA_HL_STATUS_FAIL);
+ event = BTA_HL_DCH_OPEN_CFM_EVT;
+ if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT)
+ {
+ event = BTA_HL_DCH_RECONNECT_CFM_EVT;
+ }
+ }
+ break;
+
+ case BTA_HL_DCH_OP_LOCAL_CLOSE:
+ case BTA_HL_DCH_OP_REMOTE_DELETE:
+ case BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT:
+ case BTA_HL_DCH_OP_NONE:
+
+ bta_hl_build_dch_close_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_dcb->mdl_handle,
+ BTA_HL_STATUS_OK);
+ event = BTA_HL_DCH_CLOSE_CFM_EVT;
+ break;
+
+ case BTA_HL_DCH_OP_REMOTE_CLOSE:
+ bta_hl_build_dch_close_ind(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_dcb->mdl_handle,
+ p_dcb->intentional_close);
+ event = BTA_HL_DCH_CLOSE_IND_EVT;
+ break;
+
+ case BTA_HL_DCH_OP_REMOTE_OPEN:
+
+ if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK)
+ {
+ bta_hl_build_abort_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ BTA_HL_STATUS_OK);
+ event = BTA_HL_DCH_ABORT_CFM_EVT;
+ }
+ else if (p_dcb->abort_oper & BTA_HL_ABORT_REMOTE_MASK )
+ {
+ bta_hl_build_abort_ind(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle);
+ event = BTA_HL_DCH_ABORT_IND_EVT;
+ }
+ else
+ {
+ bta_hl_build_dch_close_ind(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_dcb->mdl_handle,
+ p_dcb->intentional_close);
+ event = BTA_HL_DCH_CLOSE_IND_EVT;
+ }
+ break;
+
+ case BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST:
+ /* this is normal echo test close */
+ case BTA_HL_DCH_OP_REMOTE_CREATE:
+ case BTA_HL_DCH_OP_REMOTE_RECONNECT:
+ send_evt=FALSE;
+ break;
+
+ default:
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+ APPL_TRACE_ERROR1("DCH operation not found oper=%s", bta_hl_dch_oper_code(p_dcb->dch_oper));
+#else
+ APPL_TRACE_ERROR1("DCH operation not found oper=%d", p_dcb->dch_oper);
+#endif
+#endif
+ send_evt=FALSE;
+ break;
+ }
+
+ if ( p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID )
+ {
+ p_mcb->echo_test = FALSE;
+ send_evt=FALSE;
+
+ if ( p_dcb->dch_oper != BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST)
+ {
+ switch (p_dcb->echo_oper)
+ {
+ case BTA_HL_ECHO_OP_CI_GET_ECHO_DATA:
+ case BTA_HL_ECHO_OP_SDP_INIT:
+ case BTA_HL_ECHO_OP_MDL_CREATE_CFM:
+ case BTA_HL_ECHO_OP_DCH_OPEN_CFM:
+ case BTA_HL_ECHO_OP_LOOP_BACK:
+
+ status = BTA_HL_STATUS_FAIL;
+ send_evt = TRUE;
+ break;
+ case BTA_HL_ECHO_OP_OPEN_IND:
+ case BTA_HL_ECHO_OP_ECHO_PKT:
+ break;
+ default:
+ APPL_TRACE_ERROR1("Invalid echo_oper=%d", p_dcb->echo_oper);
+ break;
+ }
+ }
+ else
+ {
+ status = p_dcb->ci_put_echo_data_status;
+ send_evt = TRUE;
+ }
+
+ if (send_evt)
+ {
+ bta_hl_build_echo_test_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ status);
+ event = BTA_HL_DCH_ECHO_TEST_CFM_EVT;
+ }
+ }
+
+ bta_hl_clean_mdl_cb(app_idx, mcl_idx, mdl_idx);
+
+ if (send_evt)
+ {
+ if (p_acb->p_cback)
+ {
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+ APPL_TRACE_DEBUG1("Send Event: %s", bta_hl_cback_evt_code(event));
+#else
+ APPL_TRACE_DEBUG1("Send Event: 0x%02x", event);
+#endif
+#endif
+ p_acb->p_cback(event,(tBTA_HL *) &evt_data );
+ }
+ }
+ /* check cch close is in progress or not */
+ bta_hl_check_cch_close(app_idx, mcl_idx, p_data, FALSE);
+}
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_close_ind
+**
+** Description Action routine for processing the close indication
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_close_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+ APPL_TRACE_DEBUG1("bta_hl_dch_mca_close_ind dch oper=%s", bta_hl_dch_oper_code(p_dcb->dch_oper));
+#else
+ APPL_TRACE_DEBUG1("bta_hl_dch_mca_close_ind dch oper=%d", p_dcb->dch_oper);
+#endif
+#endif
+
+ p_dcb->intentional_close = FALSE;
+ if (p_data->mca_evt.mca_data.close_ind.reason == L2CAP_DISC_OK)
+ {
+ p_dcb->intentional_close = TRUE;
+ }
+
+ if (!p_dcb->cout_oper)
+ {
+ if ((p_dcb->dch_oper != BTA_HL_DCH_OP_REMOTE_OPEN) &&
+ (p_dcb->dch_oper != BTA_HL_DCH_OP_REMOTE_RECONNECT))
+ {
+ p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_CLOSE;
+ }
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ else
+ {
+ p_dcb->close_pending = TRUE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_close_cfm
+**
+** Description Action routine for processing the close confirmation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_close_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+ APPL_TRACE_DEBUG1("bta_hl_dch_mca_close_cfm dch_oper=%s", bta_hl_dch_oper_code(p_dcb->dch_oper) );
+#else
+ APPL_TRACE_DEBUG1("bta_hl_dch_mca_close_cfm dch_oper=%d", p_dcb->dch_oper);
+#endif
+#endif
+
+ switch (p_dcb->dch_oper)
+ {
+ case BTA_HL_DCH_OP_LOCAL_CLOSE:
+ case BTA_HL_DCH_OP_LOCAL_OPEN:
+ case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+ case BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST:
+ case BTA_HL_DCH_OP_REMOTE_DELETE:
+ case BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT:
+ case BTA_HL_DCH_OP_NONE:
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ break;
+ default:
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+ APPL_TRACE_ERROR1("Invalid dch_oper=%s for close cfm", bta_hl_dch_oper_code(p_dcb->dch_oper) );
+#else
+ APPL_TRACE_ERROR1("Invalid dch_oper=%d for close cfm", p_dcb->dch_oper);
+#endif
+#endif
+ break;
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_close
+**
+** Description Action routine for processing the DCH close request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_close(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ tBTA_HL evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_close");
+#endif
+ if (!p_dcb->cout_oper)
+ {
+ p_dcb->close_pending = FALSE;
+ if (MCA_CloseReq((tMCA_DL)p_dcb->mdl_handle)== MCA_SUCCESS)
+ {
+ p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_FAIL;
+ }
+
+ if ((status != BTA_HL_STATUS_OK) &&
+ (p_mcb->cch_close_dch_oper != BTA_HL_CCH_CLOSE_OP_DCH_CLOSE))
+ {
+ bta_hl_build_dch_close_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_data->api_dch_close.mdl_handle,
+ status);
+ p_acb->p_cback(BTA_HL_DCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+ }
+ else
+ {
+ p_dcb->close_pending = TRUE;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_open_ind
+**
+** Description Action routine for processing the open indication
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_open_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_DL_OPEN *p_open_ind = &p_data->mca_evt.mca_data.open_ind;
+ tBTA_HL evt_data;
+ tBTA_HL_EVT event;
+ UINT8 old_dch_oper;
+ BOOLEAN send_event = FALSE;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_open_ind");
+#endif
+ if ((p_dcb->dch_oper == BTA_HL_DCH_OP_REMOTE_OPEN) ||
+ (p_dcb->dch_oper == BTA_HL_DCH_OP_REMOTE_RECONNECT) )
+ {
+ p_dcb->mdl_handle = (tBTA_HL_MDL_HANDLE) p_open_ind->mdl;
+ p_dcb->mtu = p_open_ind->mtu;
+
+ evt_data.dch_open_ind.mdl_handle = p_dcb->mdl_handle;
+ evt_data.dch_open_ind.mcl_handle = p_mcb->mcl_handle;
+ evt_data.dch_open_ind.app_handle = p_acb->app_handle;
+
+ evt_data.dch_open_ind.local_mdep_id = p_dcb->local_mdep_id;
+ evt_data.dch_open_ind.mdl_id = p_dcb->mdl_id;
+ evt_data.dch_open_ind.mtu = p_dcb->mtu;
+
+ if ( p_dcb->chnl_cfg.fcr_opt.mode == L2CAP_FCR_ERTM_MODE )
+ {
+ evt_data.dch_open_ind.dch_mode = BTA_HL_DCH_MODE_RELIABLE;
+ if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx))
+ {
+ p_dcb->is_the_first_reliable = TRUE;
+ }
+ }
+ else
+ {
+ evt_data.dch_open_ind.dch_mode = BTA_HL_DCH_MODE_STREAMING;
+ }
+ evt_data.dch_open_ind.first_reliable = p_dcb->is_the_first_reliable ;
+
+ old_dch_oper = p_dcb->dch_oper;
+ p_dcb->dch_oper = BTA_HL_DCH_OP_NONE;
+
+
+ }
+
+ switch (old_dch_oper)
+ {
+ case BTA_HL_DCH_OP_REMOTE_OPEN:
+
+ p_dcb->dch_mode = evt_data.dch_open_ind.dch_mode;
+ if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ bta_hl_save_mdl_cfg(app_idx, mcl_idx,mdl_idx);
+ event= BTA_HL_DCH_OPEN_IND_EVT;
+ send_event= TRUE;
+ }
+ else
+ {
+ p_dcb->echo_oper = BTA_HL_ECHO_OP_ECHO_PKT;
+ }
+
+ break;
+
+ case BTA_HL_DCH_OP_REMOTE_RECONNECT:
+
+ if (bta_hl_validate_chan_cfg(app_idx, mcl_idx, mdl_idx))
+ {
+ bta_hl_save_mdl_cfg(app_idx, mcl_idx,mdl_idx);
+ event= BTA_HL_DCH_RECONNECT_IND_EVT;
+ send_event= TRUE;
+ }
+ else
+ {
+ if (MCA_CloseReq((tMCA_DL) p_dcb->mdl_handle) == MCA_SUCCESS)
+ {
+ p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("Unabel to close DCH for reconnect cfg mismatch");
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (send_event)
+ {
+ p_acb->p_cback(event ,(tBTA_HL *) &evt_data );
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_open_cfm
+**
+** Description Action routine for processing the open confirmation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_open_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_DL_OPEN *p_open_cfm = &p_data->mca_evt.mca_data.open_cfm;
+ tBTA_HL evt_data;
+ tBTA_HL_EVT event;
+ UINT8 old_dch_oper;
+ tBTA_HL_DCH_MODE dch_mode;
+ BOOLEAN send_event = FALSE;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_open_cfm");
+#endif
+ if ((p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN) ||
+ (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT))
+ {
+ p_dcb->mdl_handle = (tBTA_HL_MDL_HANDLE) p_open_cfm->mdl;
+ p_dcb->mtu = p_open_cfm->mtu;
+
+ /*todo verify dch_mode, mtu and fcs for reconnect */
+ if ( p_dcb->chnl_cfg.fcr_opt.mode == L2CAP_FCR_ERTM_MODE )
+ {
+ dch_mode = BTA_HL_DCH_MODE_RELIABLE;
+ }
+ else
+ {
+ dch_mode = BTA_HL_DCH_MODE_STREAMING;
+ }
+
+ if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ if (dch_mode == BTA_HL_DCH_MODE_RELIABLE )
+ {
+ if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx))
+ {
+ p_dcb->is_the_first_reliable = TRUE;
+ }
+ }
+ }
+
+ bta_hl_build_dch_open_cfm(&evt_data, p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_dcb->mdl_handle,
+ p_dcb->local_mdep_id,
+ p_dcb->mdl_id, dch_mode,
+ p_dcb->is_the_first_reliable,
+ p_dcb->mtu,
+ BTA_HL_STATUS_OK);
+
+ old_dch_oper = p_dcb->dch_oper;
+ p_dcb->dch_oper = BTA_HL_DCH_OP_NONE;
+ }
+
+ switch (old_dch_oper)
+ {
+ case BTA_HL_DCH_OP_LOCAL_OPEN:
+
+ p_dcb->dch_mode = dch_mode;
+ if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ bta_hl_save_mdl_cfg(app_idx, mcl_idx, mdl_idx);
+ event= BTA_HL_DCH_OPEN_CFM_EVT;
+ send_event= TRUE;
+ }
+ else
+ {
+ p_dcb->echo_oper = BTA_HL_ECHO_OP_LOOP_BACK;
+ if (MCA_WriteReq((tMCA_DL) p_dcb->mdl_handle, p_dcb->p_echo_tx_pkt)!= MCA_SUCCESS)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
+ }
+ else
+ {
+ p_dcb->p_echo_tx_pkt = NULL;
+ }
+ }
+ break;
+
+ case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+
+ if (bta_hl_validate_chan_cfg(app_idx, mcl_idx, mdl_idx))
+ {
+ bta_hl_save_mdl_cfg(app_idx, mcl_idx,mdl_idx);
+ event= BTA_HL_DCH_RECONNECT_CFM_EVT;
+ send_event= TRUE;
+ }
+ else
+ {
+ if (MCA_CloseReq((tMCA_DL) p_dcb->mdl_handle) == MCA_SUCCESS)
+ {
+ p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("Unabel to close DCH for reconnect cfg mismatch");
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (send_event)
+ p_acb->p_cback(event ,(tBTA_HL *) &evt_data );
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_abort_ind
+**
+** Description Action routine for processing the abort indication
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_abort_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_abort_ind");
+#endif
+
+ p_dcb->abort_oper |= BTA_HL_ABORT_REMOTE_MASK;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_abort_cfm
+**
+** Description Action routine for processing the abort confirmation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_abort_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_abort_cfm");
+#endif
+
+ if (p_dcb->abort_oper)
+ {
+ if (p_data->mca_evt.mca_data.abort_cfm.rsp_code != MCA_RSP_SUCCESS )
+ {
+ if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK)
+ {
+ bta_hl_build_abort_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ BTA_HL_STATUS_FAIL);
+ p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT ,(tBTA_HL *) &evt_data );
+ }
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("Not expecting Abort CFM ");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_abort
+**
+** Description Action routine for processing the abort request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_abort(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_RESULT mca_result;
+ tBTA_HL evt_data;
+
+ if (((p_mcb->sdp_oper == BTA_HL_SDP_OP_DCH_OPEN_INIT) ||
+ (p_mcb->sdp_oper == BTA_HL_SDP_OP_DCH_RECONNECT_INIT)) &&
+ (p_mcb->sdp_mdl_idx == mdl_idx) )
+ {
+ p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
+ return;
+ }
+ else if (p_dcb->echo_oper == BTA_HL_ECHO_OP_CI_GET_ECHO_DATA)
+ {
+ p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
+ return;
+ }
+
+ p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
+
+ if ((mca_result = MCA_Abort((tMCA_CL) p_mcb->mcl_handle))!= MCA_SUCCESS)
+ {
+ if (mca_result == MCA_NO_RESOURCES)
+ {
+ p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
+ }
+ else
+ {
+ if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK)
+ {
+ bta_hl_build_abort_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ BTA_HL_STATUS_FAIL);
+ p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT ,(tBTA_HL *) &evt_data );
+ }
+ bta_hl_check_cch_close(app_idx, mcl_idx, p_data, FALSE);
+ }
+
+
+ }
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG1("bta_hl_dch_mca_abort abort_oper=0x%x", p_dcb->abort_oper);
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_reconnect_ind
+**
+** Description Action routine for processing the reconnect indication
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_reconnect_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL_MDL_CFG *p_mdl_cfg;
+ tMCA_EVT_HDR *p_reconnect_ind = &p_data->mca_evt.mca_data.reconnect_ind;
+ UINT8 mdl_cfg_idx, in_use_mdl_idx, mdep_cfg_idx;
+ UINT8 rsp_code = MCA_RSP_SUCCESS;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG1("bta_hl_dch_mca_reconnect_ind mdl_id=%d", p_reconnect_ind->mdl_id);
+#endif
+
+ if (bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_reconnect_ind->mdl_id, &mdl_cfg_idx))
+ {
+ if (!bta_hl_find_mdl_idx(app_idx,mcl_idx,p_reconnect_ind->mdl_id, &in_use_mdl_idx) )
+ {
+ p_mdl_cfg = BTA_HL_GET_MDL_CFG_PTR(app_idx, mdl_cfg_idx);
+
+ if (bta_hl_find_mdep_cfg_idx(app_idx, p_mdl_cfg->local_mdep_id, &mdep_cfg_idx))
+ {
+ p_dcb->in_use = TRUE;
+ p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_RECONNECT;
+ p_dcb->sec_mask = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ p_dcb->peer_mdep_id = 0xFF;
+ p_dcb->local_mdep_id = p_mdl_cfg->local_mdep_id ;
+ p_dcb->local_mdep_cfg_idx = mdep_cfg_idx;
+ p_dcb->local_cfg = BTA_HL_DCH_CFG_UNKNOWN;
+ p_dcb->mdl_id = p_reconnect_ind->mdl_id;
+ p_dcb->mdl_cfg_idx_included = TRUE;
+ p_dcb->mdl_cfg_idx = mdl_cfg_idx;
+ p_dcb->dch_mode = p_mdl_cfg->dch_mode;
+ bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
+ &p_dcb->max_rx_apdu_size,
+ &p_dcb->max_tx_apdu_size);
+ bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+ }
+ else
+ {
+ rsp_code = MCA_RSP_BAD_MDL;
+ }
+ }
+ else
+ {
+ rsp_code = MCA_RSP_BAD_MDL;
+ }
+ }
+ else
+ {
+ rsp_code = MCA_RSP_BAD_MDL;
+ }
+
+ if (MCA_ReconnectMdlRsp((tMCA_CL) p_mcb->mcl_handle,
+ p_dcb->local_mdep_id,
+ p_dcb->mdl_id,
+ rsp_code,
+ &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+ {
+ MCA_Abort((tMCA_CL) p_mcb->mcl_handle);
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_reconnect_cfm
+**
+** Description Action routine for processing the reconenct confirmation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_reconnect_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_RSP_EVT *p_reconnect_cfm = &p_data->mca_evt.mca_data.reconnect_cfm;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_reconnect_cfm");
+#endif
+ if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK)
+ {
+ p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT, p_data);
+ return;
+ }
+
+
+ if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT)
+ {
+ if (p_reconnect_cfm->rsp_code == MCA_RSP_SUCCESS)
+ {
+
+ bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+
+ if (MCA_DataChnlCfg((tMCA_CL) p_mcb->mcl_handle, &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+ {
+ /* should be able to abort so no checking of the return code */
+ MCA_Abort((tMCA_CL) p_mcb->mcl_handle);
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_reconnect
+**
+** Description Action routine for processing the reconnect request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_reconnect(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_CHNL_CFG *p_chnl_cfg=NULL;
+ UINT8 sdp_idx;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_reconnect");
+#endif
+ if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->ctrl_psm, &sdp_idx))
+ {
+ p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
+ if ( MCA_ReconnectMdl((tMCA_CL) p_mcb->mcl_handle,
+ p_dcb->local_mdep_id,
+ p_mcb->data_psm,
+ p_dcb->mdl_id,
+ p_chnl_cfg ) != MCA_SUCCESS)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_create_rsp
+**
+** Description Action routine for processing BTA_HL_API_DCH_CREATE_RSP_EVT
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_create_rsp(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL_API_DCH_CREATE_RSP *p_create_rsp = &p_data->api_dch_create_rsp;
+ UINT8 mca_rsp_code = MCA_RSP_SUCCESS;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_create_rsp");
+#endif
+ if (p_create_rsp->rsp_code == BTA_HL_DCH_CREATE_RSP_SUCCESS)
+ {
+ p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_OPEN;
+ p_dcb->local_cfg = p_create_rsp->cfg_rsp;
+
+
+
+ bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+ }
+ else
+ {
+ mca_rsp_code = MCA_RSP_CFG_REJ;
+ }
+
+ if (MCA_CreateMdlRsp((tMCA_CL) p_mcb->mcl_handle,
+ p_dcb->local_mdep_id,
+ p_dcb->mdl_id,
+ p_dcb->local_cfg,
+ mca_rsp_code,
+ &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_create_ind
+**
+** Description Action routine for processing
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_create_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_CREATE_IND *p_create_ind = &p_data->mca_evt.mca_data.create_ind;
+ UINT8 mdep_cfg_idx;
+ UINT8 cfg_rsp;
+ UINT8 rsp_code = MCA_RSP_SUCCESS;
+ BOOLEAN send_create_ind_evt = FALSE;
+ tBTA_HL evt_data;
+ tBTA_HL_ECHO_CFG *p_echo_cfg;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_create_ind");
+#endif
+
+ if (bta_hl_find_mdep_cfg_idx(app_idx, p_create_ind->dep_id, &mdep_cfg_idx))
+ {
+ if (p_create_ind->dep_id == BTA_HL_ECHO_TEST_MDEP_ID )
+ {
+ if (bta_hl_find_echo_cfg_rsp(app_idx, mcl_idx, mdep_cfg_idx,p_create_ind->cfg, &cfg_rsp ))
+ {
+ p_dcb->in_use = TRUE;
+ p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_OPEN;
+ p_dcb->local_mdep_id = p_create_ind->dep_id ;
+ p_dcb->local_mdep_cfg_idx = mdep_cfg_idx;
+ p_dcb->local_cfg = cfg_rsp;
+ p_dcb->remote_cfg = p_create_ind->cfg ;
+ p_dcb->mdl_id = p_create_ind->mdl_id;
+ p_dcb->mdl_cfg_idx_included = FALSE;
+ p_echo_cfg = BTA_HL_GET_ECHO_CFG_PTR(app_idx);
+ p_dcb->max_rx_apdu_size = p_echo_cfg->max_rx_apdu_size;
+ p_dcb->max_tx_apdu_size = p_echo_cfg->max_tx_apdu_size;
+
+ bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+ }
+ else
+ {
+ rsp_code = MCA_RSP_CFG_REJ;
+ }
+ }
+ else
+
+ {
+ p_dcb->in_use = TRUE;
+ p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_CREATE;
+ p_dcb->local_mdep_id = p_create_ind->dep_id ;
+ p_dcb->local_mdep_cfg_idx = mdep_cfg_idx;
+ p_dcb->local_cfg = BTA_HL_DCH_CFG_UNKNOWN;
+ p_dcb->remote_cfg = p_create_ind->cfg;
+ p_dcb->mdl_id = p_create_ind->mdl_id;
+ p_dcb->mdl_cfg_idx_included = FALSE;
+ bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
+ &p_dcb->max_rx_apdu_size,
+ &p_dcb->max_tx_apdu_size);
+ send_create_ind_evt = TRUE;
+ }
+ }
+ else
+ {
+ rsp_code = MCA_RSP_BAD_MDEP;
+ }
+
+ if (send_create_ind_evt)
+ {
+ evt_data.dch_create_ind.mcl_handle = p_mcb->mcl_handle;
+ evt_data.dch_create_ind.app_handle = p_acb->app_handle;
+ evt_data.dch_create_ind.local_mdep_id = p_dcb->local_mdep_id;
+ evt_data.dch_create_ind.mdl_id = p_dcb->mdl_id;
+ evt_data.dch_create_ind.cfg = p_dcb->remote_cfg;
+ p_acb->p_cback(BTA_HL_DCH_CREATE_IND_EVT,(tBTA_HL *) &evt_data );
+ }
+ else
+ {
+ if (MCA_CreateMdlRsp((tMCA_CL) p_mcb->mcl_handle,
+ p_dcb->local_mdep_id,
+ p_dcb->mdl_id,
+ p_dcb->local_cfg,
+ rsp_code,
+ &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ else
+ {
+ if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ p_mcb->echo_test = TRUE;
+ p_dcb->echo_oper = BTA_HL_ECHO_OP_OPEN_IND;
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_create_cfm
+**
+** Description Action routine for processing
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_create_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_CREATE_CFM *p_create_cfm = &p_data->mca_evt.mca_data.create_cfm;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_create_cfm");
+#endif
+
+ if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK)
+ {
+ p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT, p_data);
+ return;
+ }
+
+ if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN)
+ {
+ if (p_create_cfm->rsp_code == MCA_RSP_SUCCESS)
+ {
+ if (bta_hl_validate_cfg(app_idx, mcl_idx, mdl_idx, p_create_cfm->cfg ))
+ {
+ bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+
+ if (MCA_DataChnlCfg((tMCA_CL) p_mcb->mcl_handle, &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+ {
+ /* this should not happen */
+ APPL_TRACE_ERROR0("Unable to create data channel");
+ MCA_Abort((tMCA_CL) p_mcb->mcl_handle);
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ else
+ {
+ if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ p_dcb->echo_oper = BTA_HL_ECHO_OP_DCH_OPEN_CFM;
+ }
+ }
+ }
+ else
+ {
+ MCA_Abort((tMCA_CL) p_mcb->mcl_handle);
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("MCA Create- failed");
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_mca_create
+**
+** Description Action routine for processing the MDL create request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_create(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tMCA_RESULT result;
+ UINT8 sdp_idx;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_dch_mca_create");
+#endif
+
+ if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->ctrl_psm, &sdp_idx) &&
+ bta_hl_validate_peer_cfg(app_idx, mcl_idx, mdl_idx,
+ p_dcb->peer_mdep_id,
+ p_dcb->peer_mdep_role,
+ sdp_idx))
+ {
+
+ p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
+ if ( (result = MCA_CreateMdl((tMCA_CL) p_mcb->mcl_handle,
+ p_dcb->local_mdep_id,
+ p_mcb->data_psm,
+ p_dcb->mdl_id,
+ p_dcb->peer_mdep_id,
+ p_dcb->local_cfg,
+ NULL )) != MCA_SUCCESS)
+ {
+ APPL_TRACE_ERROR1("MCA_CreateMdl FAIL mca_result=%d", result);
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("MCA Create- SDP idx or peer MDEP cfg not found");
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_sdp_fail
+**
+** Description Action routine for processing the SDP failed event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_sdp_fail(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data)
+{
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_dch_sdp_fail");
+#endif
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+}
+
+/******************************************************************************
+**
+** Function bta_hl_sdp_cback
+**
+** Description This is the SDP callback function used by HL.
+** This function will be executed by SDP when the service
+** search is completed. If the search is successful, it
+** finds the first record in the database that matches the
+** UUID of the search. Then retrieves the scn from the
+** record.
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback(UINT8 sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx, UINT16 status)
+{
+ tBTA_HL_MCL_CB *p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_SDP_REC *p_hdp_rec;
+ tBTA_HL_CCH_SDP *p_cch_buf;
+ tBTA_HL_DCH_SDP *p_dch_buf;
+ tSDP_DISC_REC *p_rec = NULL;
+ tSDP_PROTOCOL_ELEM pe;
+ tSDP_DISC_ATTR *p_attr;
+ UINT8 i, rec_cnt;
+ tBTA_HL_SUP_FEATURE_LIST_ELEM sup_feature;
+ BOOLEAN sdp_parsing_ok =FALSE, result=FALSE;
+ UINT16 event;
+ tBTA_HL_MDL_CB *p_dcb;
+ UINT16 service_uuid;
+ UINT16 name_len;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG5("bta_hl_sdp_cback status:%d sdp_oper=%d app_idx=%d, mcl_idx=%d, mdl_idx=%d",
+ status, sdp_oper, app_idx, mcl_idx, mdl_idx);
+#endif
+
+ rec_cnt = 0;
+ service_uuid = bta_hl_get_service_uuids(sdp_oper, app_idx, mcl_idx, mdl_idx);
+
+ if (status == SDP_SUCCESS || status == SDP_DB_FULL)
+ {
+ memset(&p_cb->sdp,0, sizeof(tBTA_HL_SDP));
+ do
+ {
+ if (bta_hl_find_service_in_db(app_idx, mcl_idx, service_uuid, &p_rec))
+ {
+ p_hdp_rec = &p_cb->sdp.sdp_rec[rec_cnt];
+ p_cb->sdp.num_recs = rec_cnt+1;
+ }
+ else
+ {
+ break;
+ }
+
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_L2CAP, &pe))
+ {
+ p_hdp_rec->ctrl_psm = (UINT16) pe.params[0];
+ }
+ else
+ {
+ APPL_TRACE_WARNING0("Control PSM not found");
+ break;
+ }
+ if (SDP_FindAddProtoListsElemInRec(p_rec, UUID_PROTOCOL_L2CAP, &pe))
+ {
+ p_hdp_rec->data_psm = (UINT16) pe.params[0];
+ }
+ else
+ {
+ APPL_TRACE_WARNING0("Data PSM not found");
+ break;
+ }
+
+ p_hdp_rec->srv_name[0]= '\0';
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+ {
+ if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
+ name_len = (UINT16)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ else
+ name_len = BT_MAX_SERVICE_NAME_LEN;
+ memcpy(p_hdp_rec->srv_name, p_attr->attr_value.v.array, name_len);
+ }
+
+ p_hdp_rec->srv_desp[0]= '\0';
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_DESCRIPTION)) != NULL)
+ {
+ if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
+ name_len = (UINT16)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ else
+ name_len = BT_MAX_SERVICE_NAME_LEN;
+ memcpy(p_hdp_rec->srv_desp, p_attr->attr_value.v.array, name_len);
+ }
+
+
+ p_hdp_rec->provider_name[0]= '\0';
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PROVIDER_NAME)) != NULL)
+ {
+ if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
+ name_len = (UINT16)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ else
+ name_len = BT_MAX_SERVICE_NAME_LEN;
+ memcpy(p_hdp_rec->provider_name, p_attr->attr_value.v.array, name_len);
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HDP_MCAP_SUP_PROC))!=NULL)
+ {
+ p_hdp_rec->mcap_sup_proc = p_attr->attr_value.v.u8;
+ }
+ else
+ {
+ APPL_TRACE_WARNING0("MCAP SUP PROC not found");
+ break;
+ }
+
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HDP_SUP_FEAT_LIST ))!=NULL)
+ {
+ if (bta_hl_fill_sup_feature_list (p_attr, &sup_feature))
+ {
+ p_hdp_rec->num_mdeps = (UINT8) sup_feature.num_elems;
+ for (i=0; i<sup_feature.num_elems; i++)
+ {
+ p_hdp_rec->mdep_cfg[i].data_type = sup_feature.list_elem[i].data_type;
+ p_hdp_rec->mdep_cfg[i].mdep_id = sup_feature.list_elem[i].mdep_id;
+ p_hdp_rec->mdep_cfg[i].mdep_role = sup_feature.list_elem[i].mdep_role;
+ /* Check MDEP Description pointer to prevent crash due to null pointer */
+ if (sup_feature.list_elem[i].p_mdep_desp != NULL)
+ {
+ BCM_STRNCPY_S(p_hdp_rec->mdep_cfg[i].mdep_desp,
+ sizeof(p_hdp_rec->mdep_cfg[i].mdep_desp),
+ sup_feature.list_elem[i].p_mdep_desp,
+ BTA_HL_MDEP_DESP_LEN);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_hl_sdp_cback Incorrect Mdep[%d] Description (Null ptr)", i);
+ }
+ }
+
+ sdp_parsing_ok = TRUE;
+ }
+ else
+ {
+ APPL_TRACE_WARNING0("HDP supported feature list fill failed");
+ break;
+ }
+ }
+ else
+ {
+ APPL_TRACE_WARNING0("HDP supported feature list not found");
+ break;
+ }
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG3("record=%d ctrl_psm=%0x data_psm=%x",
+ rec_cnt+1,
+ p_hdp_rec->ctrl_psm,
+ p_hdp_rec->data_psm );
+ APPL_TRACE_DEBUG1("srv_name=[%s]",(p_hdp_rec->srv_name[0] != '\0')? p_hdp_rec->srv_name:"NULL");
+ APPL_TRACE_DEBUG1("srv_desp=[%s]",(p_hdp_rec->srv_desp[0] != '\0')? p_hdp_rec->srv_desp:"NULL");
+ for (i=0; i<sup_feature.num_elems; i++)
+ {
+ APPL_TRACE_DEBUG5("index=0x%02x mdep_id=0x%04x data type=0x%04x mdep role=%s(0x%02x)",
+ (i+1),
+ p_hdp_rec->mdep_cfg[i].mdep_id,
+ p_hdp_rec->mdep_cfg[i].data_type,
+ (p_hdp_rec->mdep_cfg[i].mdep_role == BTA_HL_MDEP_ROLE_SOURCE)?"Src":"Snk",
+ p_hdp_rec->mdep_cfg[i].mdep_role);
+ }
+ APPL_TRACE_DEBUG1("provider_name=[%s]",(p_hdp_rec->provider_name[0] != '\0')? p_hdp_rec->provider_name:"NULL");
+ APPL_TRACE_DEBUG1("found MCAP sup procedure=%d",
+ p_cb->sdp.sdp_rec[rec_cnt].mcap_sup_proc );
+#endif
+ rec_cnt++;
+ if (rec_cnt >= BTA_HL_NUM_SDP_RECS)
+ {
+ APPL_TRACE_WARNING1("No more spaces for SDP recs max_rec_cnt=%d", BTA_HL_NUM_SDP_RECS);
+ break;
+ }
+
+
+ } while (TRUE);
+ }
+
+
+ utl_freebuf((void **)&p_cb->p_db);
+
+ if ( (status == SDP_SUCCESS || status == SDP_DB_FULL) &&
+ p_cb->sdp.num_recs &&
+ sdp_parsing_ok)
+ {
+ result = TRUE;
+ }
+ else
+ {
+ APPL_TRACE_WARNING3("SDP Failed sdp_status=%d num_recs=%d sdp_parsing_ok=%d ",
+ status, p_cb->sdp.num_recs,sdp_parsing_ok );
+ }
+
+
+ p_cb->sdp_oper = BTA_HL_SDP_OP_NONE;
+
+ switch (sdp_oper )
+ {
+ case BTA_HL_SDP_OP_CCH_INIT:
+ case BTA_HL_SDP_OP_SDP_QUERY_NEW:
+ case BTA_HL_SDP_OP_SDP_QUERY_CURRENT:
+
+ /* send result in event back to BTA */
+ if ((p_cch_buf = (tBTA_HL_CCH_SDP *) GKI_getbuf(sizeof(tBTA_HL_CCH_SDP))) != NULL)
+ {
+ if (result)
+ {
+ if (sdp_oper == BTA_HL_SDP_OP_CCH_INIT)
+ {
+ event = BTA_HL_CCH_SDP_OK_EVT;
+ if (p_cb->close_pending)
+ {
+ event = BTA_HL_CCH_SDP_FAIL_EVT;
+ }
+ }
+ else
+ {
+ event = BTA_HL_SDP_QUERY_OK_EVT;
+ }
+ }
+ else
+ {
+ if (sdp_oper == BTA_HL_SDP_OP_CCH_INIT)
+ {
+ event = BTA_HL_CCH_SDP_FAIL_EVT;
+ }
+ else
+ {
+ event = BTA_HL_SDP_QUERY_FAIL_EVT;
+ }
+ }
+ p_cch_buf->hdr.event = event;
+
+ p_cch_buf->app_idx = app_idx;
+ p_cch_buf->mcl_idx = mcl_idx;
+ p_cch_buf->release_mcl_cb = FALSE;
+ if (sdp_oper == BTA_HL_SDP_OP_SDP_QUERY_NEW)
+ {
+ p_cch_buf->release_mcl_cb = TRUE;
+ }
+
+ bta_sys_sendmsg(p_cch_buf);
+ }
+ break;
+ case BTA_HL_SDP_OP_DCH_OPEN_INIT:
+ case BTA_HL_SDP_OP_DCH_RECONNECT_INIT:
+ if ((p_dch_buf = (tBTA_HL_DCH_SDP *) GKI_getbuf(sizeof(tBTA_HL_DCH_SDP))) != NULL)
+ {
+ p_dch_buf->hdr.event = BTA_HL_DCH_SDP_FAIL_EVT;
+ p_dch_buf->app_idx = app_idx;
+ p_dch_buf->mcl_idx = mcl_idx;
+ p_dch_buf->mdl_idx = mdl_idx;
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK)
+ {
+ p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
+ result = FALSE;
+ }
+ if (result)
+ {
+ if (sdp_oper == BTA_HL_SDP_OP_DCH_OPEN_INIT)
+ {
+ if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID )
+ {
+ p_dch_buf->hdr.event = BTA_HL_DCH_ECHO_TEST_EVT;
+ }
+ else
+ {
+ p_dch_buf->hdr.event = BTA_HL_DCH_OPEN_EVT;
+ }
+ }
+ else
+ {
+ p_dch_buf->hdr.event = BTA_HL_DCH_RECONNECT_EVT;
+ }
+ }
+ bta_sys_sendmsg(p_dch_buf);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+
+/******************************************************************************
+**
+** Function bta_hl_sdp_cback0
+**
+** Description This is the SDP callback function used by index = 0
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback0(UINT16 status)
+{
+ bta_hl_sdp_cback(bta_hl_cb.scb[0].sdp_oper,
+ bta_hl_cb.scb[0].app_idx,
+ bta_hl_cb.scb[0].mcl_idx,
+ bta_hl_cb.scb[0].mdl_idx,
+ status);
+ bta_hl_deallocate_spd_cback(0);
+}
+
+/******************************************************************************
+**
+** Function bta_hl_sdp_cback1
+**
+** Description This is the SDP callback function used by index = 1
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback1(UINT16 status)
+{
+ bta_hl_sdp_cback(bta_hl_cb.scb[1].sdp_oper,
+ bta_hl_cb.scb[1].app_idx,
+ bta_hl_cb.scb[1].mcl_idx,
+ bta_hl_cb.scb[1].mdl_idx,
+ status);
+ bta_hl_deallocate_spd_cback(1);
+}
+
+/******************************************************************************
+**
+** Function bta_hl_sdp_cback2
+**
+** Description This is the SDP callback function used by index = 2
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback2(UINT16 status)
+{
+ bta_hl_sdp_cback(bta_hl_cb.scb[2].sdp_oper,
+ bta_hl_cb.scb[2].app_idx,
+ bta_hl_cb.scb[2].mcl_idx,
+ bta_hl_cb.scb[2].mdl_idx,
+ status);
+ bta_hl_deallocate_spd_cback(2);
+}
+
+/******************************************************************************
+**
+** Function bta_hl_sdp_cback3
+**
+** Description This is the SDP callback function used by index = 3
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback3(UINT16 status)
+{
+ bta_hl_sdp_cback(bta_hl_cb.scb[3].sdp_oper,
+ bta_hl_cb.scb[3].app_idx,
+ bta_hl_cb.scb[3].mcl_idx,
+ bta_hl_cb.scb[3].mdl_idx,
+ status);
+ bta_hl_deallocate_spd_cback(3);
+}
+
+/******************************************************************************
+**
+** Function bta_hl_sdp_cback4
+**
+** Description This is the SDP callback function used by index = 4
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback4(UINT16 status)
+{
+ bta_hl_sdp_cback(bta_hl_cb.scb[4].sdp_oper,
+ bta_hl_cb.scb[4].app_idx,
+ bta_hl_cb.scb[4].mcl_idx,
+ bta_hl_cb.scb[4].mdl_idx,
+ status);
+ bta_hl_deallocate_spd_cback(4);
+}
+
+/******************************************************************************
+**
+** Function bta_hl_sdp_cback5
+**
+** Description This is the SDP callback function used by index = 5
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback5(UINT16 status)
+{
+ bta_hl_sdp_cback(bta_hl_cb.scb[5].sdp_oper,
+ bta_hl_cb.scb[5].app_idx,
+ bta_hl_cb.scb[5].mcl_idx,
+ bta_hl_cb.scb[5].mdl_idx,
+ status);
+ bta_hl_deallocate_spd_cback(5);
+}
+
+/******************************************************************************
+**
+** Function bta_hl_sdp_cback6
+**
+** Description This is the SDP callback function used by index = 6
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback6(UINT16 status)
+{
+ bta_hl_sdp_cback(bta_hl_cb.scb[6].sdp_oper,
+ bta_hl_cb.scb[6].app_idx,
+ bta_hl_cb.scb[6].mcl_idx,
+ bta_hl_cb.scb[6].mdl_idx,
+ status);
+ bta_hl_deallocate_spd_cback(6);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_deallocate_spd_cback
+**
+** Description Deallocate a SDP control block
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+void bta_hl_deallocate_spd_cback(UINT8 sdp_cback_idx)
+{
+ tBTA_HL_SDP_CB *p_spd_cb = &bta_hl_cb.scb[sdp_cback_idx];
+
+ memset(p_spd_cb, 0, sizeof(tBTA_HL_SDP_CB));
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_deallocate_spd_cback index=%d", sdp_cback_idx);
+#endif
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_allocate_spd_cback
+**
+** Description Finds a not in used SDP control block index
+**
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+tSDP_DISC_CMPL_CB *bta_hl_allocate_spd_cback(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx,
+ UINT8 *p_sdp_cback_idx)
+{
+ UINT8 i;
+ tSDP_DISC_CMPL_CB *p_cbcak=NULL;
+
+
+ for (i=0; i < BTA_HL_NUM_SDP_CBACKS ; i ++)
+ {
+ if (!bta_hl_cb.scb[i].in_use)
+ {
+ p_cbcak = bta_hl_sdp_cback_arr[i];
+ bta_hl_cb.scb[i].in_use = TRUE;
+ bta_hl_cb.scb[i].sdp_oper = sdp_oper;
+ bta_hl_cb.scb[i].app_idx = app_idx;
+ bta_hl_cb.scb[i].mcl_idx = mcl_idx;
+ bta_hl_cb.scb[i].mdl_idx = mdl_idx;
+ *p_sdp_cback_idx = i;
+ break;
+ }
+ }
+
+ if (i == BTA_HL_NUM_SDP_CBACKS)
+ {
+ APPL_TRACE_WARNING0("No scb is available to allocate")
+ }
+ else
+ {
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_allocate_spd_cback cback_idx=%d ",i );
+ APPL_TRACE_DEBUG4("sdp_oper=%d, app_idx=%d, mcl_idx=%d, mdl_idx=%d",
+ bta_hl_cb.scb[i].sdp_oper,
+ bta_hl_cb.scb[i].app_idx,
+ bta_hl_cb.scb[i].mcl_idx,
+ bta_hl_cb.scb[i].mdl_idx );
+#endif
+ }
+ return p_cbcak;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_init_sdp
+**
+** Description Action routine for processing the SDP initiattion request
+**
+** Returns void
+**
+*******************************************************************************/
+tBTA_HL_STATUS bta_hl_init_sdp(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx)
+{
+ tBTA_HL_MCL_CB *p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tSDP_UUID uuid_list;
+ UINT16 attr_list[BTA_HL_NUM_SRCH_ATTR];
+ UINT16 num_attrs = BTA_HL_NUM_SRCH_ATTR;
+ tBTA_HL_STATUS status;
+ UINT8 sdp_cback_idx;
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG4("bta_hl_init_sdp sdp_oper=%d app_idx=%d mcl_idx=%d, mdl_idx=%d",
+ sdp_oper, app_idx, mcl_idx, mdl_idx);
+#endif
+ if ((p_cb->sdp_cback = bta_hl_allocate_spd_cback(sdp_oper, app_idx, mcl_idx, mdl_idx, &sdp_cback_idx)) != NULL)
+ {
+ if ( p_cb->p_db ||
+ (!p_cb->p_db &&
+ (p_cb->p_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_HL_DISC_SIZE)) != NULL))
+ {
+ attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+ attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+ attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
+ attr_list[3] = ATTR_ID_ADDITION_PROTO_DESC_LISTS;
+ attr_list[4] = ATTR_ID_SERVICE_NAME;
+ attr_list[5] = ATTR_ID_SERVICE_DESCRIPTION;
+ attr_list[6] = ATTR_ID_PROVIDER_NAME;
+ attr_list[7] = ATTR_ID_HDP_SUP_FEAT_LIST;
+ attr_list[8] = ATTR_ID_HDP_DATA_EXCH_SPEC;
+ attr_list[9] = ATTR_ID_HDP_MCAP_SUP_PROC;
+
+
+ uuid_list.len = LEN_UUID_16;
+ uuid_list.uu.uuid16 = UUID_SERVCLASS_HDP_PROFILE;
+
+ SDP_InitDiscoveryDb(p_cb->p_db, BTA_HL_DISC_SIZE, 1, &uuid_list, num_attrs, attr_list);
+
+ if (!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db, p_cb->sdp_cback))
+ {
+ status = BTA_HL_STATUS_FAIL;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_OK;
+ }
+ }
+ else /* No services available */
+ {
+ status = BTA_HL_STATUS_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_SDP_NO_RESOURCE;
+ }
+
+ if (status != BTA_HL_STATUS_OK)
+ {
+ utl_freebuf((void **)&p_cb->p_db);
+ if (status != BTA_HL_STATUS_SDP_NO_RESOURCE )
+ {
+ bta_hl_deallocate_spd_cback(sdp_cback_idx);
+ }
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_cch_sdp_init
+**
+** Description Action routine for processing the CCH SDP init event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_sdp_init(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_MCL_CB *p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_cch_init_sdp");
+#endif
+ if ( p_cb->sdp_oper == BTA_HL_SDP_OP_NONE)
+ {
+ p_cb->sdp_oper = BTA_HL_SDP_OP_CCH_INIT;
+
+ if (bta_hl_init_sdp( p_cb->sdp_oper, app_idx, mcl_idx, 0xFF) != BTA_HL_STATUS_OK)
+ {
+ p_cb->sdp_oper = BTA_HL_SDP_OP_NONE;
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_SDP_FAIL_EVT, p_data);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("SDP in use");
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_SDP_FAIL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_cch_mca_open
+**
+** Description Action routine for processing the CCH open request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_open(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ UINT8 sdp_idx;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_cch_mca_open");
+#endif
+
+ if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->req_ctrl_psm, &sdp_idx))
+ {
+ p_mcb->ctrl_psm = p_mcb->sdp.sdp_rec[sdp_idx].ctrl_psm;
+ p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
+ if ( MCA_ConnectReq((tMCA_HANDLE) p_acb->app_handle,
+ p_mcb->bd_addr,
+ p_mcb->ctrl_psm ,
+ p_mcb->sec_mask) != MCA_SUCCESS)
+ {
+
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_cch_mca_close
+**
+** Description Action routine for processing the CCH close request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_close(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_cch_mca_close");
+#endif
+ if (p_mcb->sdp_oper != BTA_HL_SDP_OP_CCH_INIT)
+ {
+ if ( MCA_DisconnectReq((tMCA_HANDLE) p_acb->app_handle) != MCA_SUCCESS)
+ {
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else
+ {
+ p_mcb->close_pending = TRUE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_cch_close_cmpl
+**
+** Description Action routine for processing the CCH close complete event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+ tBTA_HL evt_data;
+ tBTA_HL_EVT event;
+ BOOLEAN send_evt=TRUE;
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_cch_close_cmpl");
+#endif
+ bta_sys_conn_close(BTA_ID_HL, p_acb->app_id, p_mcb->bd_addr);
+
+ switch (p_mcb->cch_oper)
+ {
+ case BTA_HL_CCH_OP_LOCAL_OPEN:
+ bta_hl_build_cch_open_cfm(&evt_data, p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_mcb->bd_addr,
+ BTA_HL_STATUS_FAIL);
+ event = BTA_HL_CCH_OPEN_CFM_EVT;
+ break;
+ case BTA_HL_CCH_OP_LOCAL_CLOSE:
+ bta_hl_build_cch_close_cfm(&evt_data, p_acb->app_handle,
+ p_mcb->mcl_handle,
+ BTA_HL_STATUS_OK);
+ event = BTA_HL_CCH_CLOSE_CFM_EVT;
+ break;
+ case BTA_HL_CCH_OP_REMOTE_CLOSE:
+ bta_hl_build_cch_close_ind(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_mcb->intentional_close);
+ event = BTA_HL_CCH_CLOSE_IND_EVT;
+ break;
+ default:
+ send_evt=FALSE;
+ break;
+ }
+
+
+ memset(p_mcb, 0 ,sizeof(tBTA_HL_MCL_CB));
+
+ if (send_evt)p_acb->p_cback(event,(tBTA_HL *) &evt_data );
+
+ bta_hl_check_deregistration(app_idx, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_cch_mca_disconnect
+**
+** Description Action routine for processing the CCH disconnect indication
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_disconnect(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
+{
+
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb;
+ UINT8 i;
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_cch_mca_disconnect");
+#endif
+
+ p_mcb->intentional_close = FALSE;
+ if (p_data->mca_evt.mca_data.disconnect_ind.reason == L2CAP_DISC_OK)
+ {
+ p_mcb->intentional_close = TRUE;
+ }
+
+ for (i=0; i< BTA_HL_NUM_MDLS_PER_MCL; i++)
+ {
+ p_dcb= BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, i);
+ if (p_dcb->in_use && (p_dcb->dch_state != BTA_HL_DCH_IDLE_ST))
+ {
+ if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE )
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, i, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, i, BTA_HL_MCA_CLOSE_IND_EVT, p_data);
+ }
+ }
+ }
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_cch_mca_rsp_tout
+**
+** Description Action routine for processing the MCAP response timeout
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_rsp_tout(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
+{
+
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_cch_mca_rsp_tout");
+#endif
+
+ p_mcb->rsp_tout = TRUE;
+
+ bta_hl_check_cch_close(app_idx,mcl_idx,p_data,TRUE);
+}
+/*******************************************************************************
+**
+** Function bta_hl_cch_mca_connect
+**
+** Description Action routine for processing the CCH connect indication
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_connect(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL evt_data;
+ tBTA_HL_EVT event;
+ BOOLEAN send_event=TRUE;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_cch_mca_connect");
+#endif
+
+ p_mcb->mcl_handle = p_data->mca_evt.mcl_handle;
+ bdcpy(p_mcb->bd_addr, p_data->mca_evt.mca_data.connect_ind.bd_addr);
+ p_mcb->cch_mtu = p_data->mca_evt.mca_data.connect_ind.mtu;
+
+ bta_sys_conn_open(BTA_ID_HL, p_acb->app_id, p_mcb->bd_addr);
+ switch (p_mcb->cch_oper)
+ {
+ case BTA_HL_CCH_OP_LOCAL_OPEN:
+ bta_hl_build_cch_open_cfm(&evt_data, p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_mcb->bd_addr,
+ BTA_HL_STATUS_OK);
+ event = BTA_HL_CCH_OPEN_CFM_EVT;
+ break;
+ case BTA_HL_CCH_OP_REMOTE_OPEN:
+ bta_hl_build_cch_open_ind(&evt_data, p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_mcb->bd_addr);
+ event = BTA_HL_CCH_OPEN_IND_EVT;
+ break;
+ default:
+ send_event = FALSE;
+ break;
+ }
+
+ p_mcb->cch_oper = BTA_HL_CCH_OP_NONE;
+ if (send_event) p_acb->p_cback(event,(tBTA_HL *) &evt_data );
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_mcap_ctrl_cback
+**
+** Description MCAP control callback function for HL.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_mcap_ctrl_cback (tMCA_HANDLE handle, tMCA_CL mcl, UINT8 event,
+ tMCA_CTRL *p_data)
+{
+ tBTA_HL_MCA_EVT * p_msg;
+ BOOLEAN send_event=TRUE;
+ UINT16 mca_event;
+
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+ APPL_TRACE_EVENT1("bta_hl_mcap_ctrl_cback event[%s]",bta_hl_mcap_evt_code(event));
+#else
+ APPL_TRACE_EVENT1("bta_hl_mcap_ctrl_cback event[0x%02x]", event);
+#endif
+#endif
+
+ switch (event)
+ {
+
+ case MCA_CREATE_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_CREATE_IND_EVT;
+ break;
+ case MCA_CREATE_CFM_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_CREATE_CFM_EVT;
+ break;
+ case MCA_RECONNECT_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_RECONNECT_IND_EVT;
+ break;
+ case MCA_RECONNECT_CFM_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_RECONNECT_CFM_EVT;
+ break;
+ case MCA_ABORT_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_ABORT_IND_EVT;
+ break;
+ case MCA_ABORT_CFM_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_ABORT_CFM_EVT;
+ break;
+ case MCA_DELETE_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_DELETE_IND_EVT;
+ break;
+ case MCA_DELETE_CFM_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_DELETE_CFM_EVT;
+ break;
+ case MCA_CONNECT_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_CONNECT_IND_EVT;
+ break;
+ case MCA_DISCONNECT_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_DISCONNECT_IND_EVT;
+ break;
+ case MCA_OPEN_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_OPEN_IND_EVT;
+ break;
+ case MCA_OPEN_CFM_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_OPEN_CFM_EVT;
+ break;
+ case MCA_CLOSE_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_CLOSE_IND_EVT;
+ break;
+ case MCA_CLOSE_CFM_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_CLOSE_CFM_EVT;
+ break;
+ case MCA_CONG_CHG_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_CONG_CHG_EVT;
+ break;
+ case MCA_RSP_TOUT_IND_EVT:
+ mca_event = (UINT16) BTA_HL_MCA_RSP_TOUT_IND_EVT;
+ break;
+ case MCA_ERROR_RSP_EVT:
+
+ default:
+ send_event=FALSE;
+ break;
+ }
+
+ if ((p_msg = (tBTA_HL_MCA_EVT *)GKI_getbuf(sizeof(tBTA_HL_MCA_EVT))) != NULL)
+ {
+ p_msg->hdr.event = mca_event;
+ p_msg->app_handle = (tBTA_HL_APP_HANDLE) handle;
+ p_msg->mcl_handle = (tBTA_HL_MCL_HANDLE) mcl;
+ memcpy (&p_msg->mca_data, p_data, sizeof(tMCA_CTRL));
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_mcap_data_cback
+**
+** Description MCAP data callback function for HL.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_mcap_data_cback (tMCA_DL mdl, BT_HDR *p_pkt)
+{
+ tBTA_HL_MCA_RCV_DATA_EVT *p_msg;
+
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ if (bta_hl_find_mdl_idx_using_handle ((tBTA_HL_MDL_HANDLE)mdl, &app_idx, &mcl_idx, &mdl_idx))
+ {
+ if ((p_msg = (tBTA_HL_MCA_RCV_DATA_EVT *)GKI_getbuf(sizeof(tBTA_HL_MCA_RCV_DATA_EVT))) != NULL)
+ {
+ p_msg->hdr.event = BTA_HL_MCA_RCV_DATA_EVT;
+ p_msg->app_idx = app_idx;
+ p_msg->mcl_idx = mcl_idx;
+ p_msg->mdl_idx = mdl_idx;
+ p_msg->p_pkt = p_pkt;
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+}
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if (BTA_HL_DEBUG == TRUE && BT_TRACE_VERBOSE == TRUE)
+
+/*******************************************************************************
+**
+** Function bta_hl_mcap_evt_code
+**
+** Description get the MCAP event string pointer
+**
+** Returns char * - event string pointer
+**
+*******************************************************************************/
+static char *bta_hl_mcap_evt_code(UINT8 evt_code)
+{
+
+ switch (evt_code)
+ {
+
+ case MCA_ERROR_RSP_EVT:
+ return "MCA_ERROR_RSP_EVT";
+ case MCA_CREATE_IND_EVT:
+ return "MCA_CREATE_IND_EVT";
+ case MCA_CREATE_CFM_EVT:
+ return "MCA_CREATE_CFM_EVT";
+ case MCA_RECONNECT_IND_EVT:
+ return "MCA_RECONNECT_IND_EVT";
+ case MCA_RECONNECT_CFM_EVT:
+ return "MCA_RECONNECT_CFM_EVT";
+ case MCA_ABORT_IND_EVT:
+ return "MCA_ABORT_IND_EVT";
+ case MCA_ABORT_CFM_EVT:
+ return "MCA_ABORT_CFM_EVT";
+ case MCA_DELETE_IND_EVT:
+ return "MCA_DELETE_IND_EVT";
+ case MCA_DELETE_CFM_EVT:
+ return "MCA_DELETE_CFM_EVT";
+
+ case MCA_CONNECT_IND_EVT:
+ return "MCA_CONNECT_IND_EVT";
+ case MCA_DISCONNECT_IND_EVT:
+ return "MCA_DISCONNECT_IND_EVT";
+ case MCA_OPEN_IND_EVT:
+ return "MCA_OPEN_IND_EVT";
+ case MCA_OPEN_CFM_EVT:
+ return "MCA_OPEN_CFM_EVT";
+ case MCA_CLOSE_IND_EVT:
+ return "MCA_CLOSE_IND_EVT";
+ case MCA_CLOSE_CFM_EVT:
+ return "MCA_CLOSE_CFM_EVT";
+ case MCA_CONG_CHG_EVT:
+ return "MCA_CONG_CHG_EVT";
+ case MCA_RSP_TOUT_IND_EVT:
+ return "MCA_RSP_TOUT_IND_EVT";
+ default:
+ return "Unknown MCAP event code";
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_cback_evt_code
+**
+** Description get the HDP event string pointer
+**
+** Returns char * - event string pointer
+**
+*******************************************************************************/
+static char *bta_hl_cback_evt_code(UINT8 evt_code)
+{
+
+ switch (evt_code)
+ {
+
+ case BTA_HL_CCH_OPEN_IND_EVT:
+ return "BTA_HL_CCH_OPEN_IND_EVT";
+ case BTA_HL_CCH_OPEN_CFM_EVT:
+ return "BTA_HL_CCH_OPEN_CFM_EVT";
+ case BTA_HL_CCH_CLOSE_IND_EVT:
+ return "BTA_HL_CCH_CLOSE_IND_EVT";
+ case BTA_HL_CCH_CLOSE_CFM_EVT:
+ return "BTA_HL_CCH_CLOSE_CFM_EVT";
+ case BTA_HL_DCH_OPEN_IND_EVT:
+ return "BTA_HL_DCH_OPEN_IND_EVT";
+ case BTA_HL_DCH_OPEN_CFM_EVT:
+ return "BTA_HL_DCH_OPEN_CFM_EVT";
+ case BTA_HL_DCH_CLOSE_IND_EVT:
+ return "BTA_HL_DCH_CLOSE_IND_EVT";
+ case BTA_HL_DCH_CLOSE_CFM_EVT:
+ return "BTA_HL_DCH_CLOSE_CFM_EVT";
+ case BTA_HL_DCH_RCV_DATA_IND_EVT:
+ return "BTA_HL_DCH_RCV_DATA_IND_EVT";
+ case BTA_HL_REGISTER_CFM_EVT:
+ return "BTA_HL_REGISTER_CFM_EVT";
+ case BTA_HL_DEREGISTER_CFM_EVT:
+ return "BTA_HL_DEREGISTER_CFM_EVT";
+ case BTA_HL_DCH_RECONNECT_CFM_EVT:
+ return "BTA_HL_DCH_RECONNECT_CFM_EVT";
+ case BTA_HL_DCH_RECONNECT_IND_EVT:
+ return "BTA_HL_DCH_RECONNECT_IND_EVT";
+ case BTA_HL_DCH_ECHO_TEST_CFM_EVT:
+ return "BTA_HL_DCH_ECHO_TEST_CFM_EVT";
+ case BTA_HL_SDP_QUERY_CFM_EVT:
+ return "BTA_HL_SDP_QUERY_CFM_EVT";
+ case BTA_HL_CONG_CHG_IND_EVT:
+ return "BTA_HL_CONG_CHG_IND_EVT";
+ case BTA_HL_DCH_CREATE_IND_EVT:
+ return "BTA_HL_DCH_CREATE_IND_EVT";
+ case BTA_HL_DELETE_MDL_IND_EVT:
+ return "BTA_HL_DELETE_MDL_IND_EVT";
+ case BTA_HL_DELETE_MDL_CFM_EVT:
+ return "BTA_HL_DELETE_MDL_CFM_EVT";
+ case BTA_HL_DCH_ABORT_IND_EVT:
+ return "BTA_HL_DCH_ABORT_IND_EVT";
+ case BTA_HL_DCH_ABORT_CFM_EVT:
+ return "BTA_HL_DCH_ABORT_CFM_EVT";
+ default:
+ return "Unknown HDP event code";
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_oper_code
+**
+** Description Get the DCH operation string
+**
+** Returns char * - DCH operation string pointer
+**
+*******************************************************************************/
+static char *bta_hl_dch_oper_code(tBTA_HL_DCH_OPER oper_code)
+{
+
+ switch (oper_code)
+ {
+ case BTA_HL_DCH_OP_NONE:
+ return "BTA_HL_DCH_OP_NONE";
+ case BTA_HL_DCH_OP_REMOTE_CREATE:
+ return "BTA_HL_DCH_OP_REMOTE_CREATE";
+ case BTA_HL_DCH_OP_LOCAL_OPEN:
+ return "BTA_HL_DCH_OP_LOCAL_OPEN";
+ case BTA_HL_DCH_OP_REMOTE_OPEN:
+ return "BTA_HL_DCH_OP_REMOTE_OPEN";
+ case BTA_HL_DCH_OP_LOCAL_CLOSE:
+ return "BTA_HL_DCH_OP_LOCAL_CLOSE";
+ case BTA_HL_DCH_OP_REMOTE_CLOSE:
+ return "BTA_HL_DCH_OP_REMOTE_CLOSE";
+ case BTA_HL_DCH_OP_LOCAL_DELETE:
+ return "BTA_HL_DCH_OP_LOCAL_DELETE";
+ case BTA_HL_DCH_OP_REMOTE_DELETE:
+ return "BTA_HL_DCH_OP_REMOTE_DELETE";
+ case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+ return "BTA_HL_DCH_OP_LOCAL_RECONNECT";
+ case BTA_HL_DCH_OP_REMOTE_RECONNECT:
+ return "BTA_HL_DCH_OP_REMOTE_RECONNECT";
+ case BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST:
+ return "BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST";
+ case BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT:
+ return "BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT";
+ default:
+ return "Unknown DCH oper code";
+ }
+}
+
+
+#endif /* Debug Functions */
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_api.c b/bta/hl/bta_hl_api.c
new file mode 100644
index 0000000..8c8d621
--- /dev/null
+++ b/bta/hl/bta_hl_api.c
@@ -0,0 +1,485 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation of the API for the HeaLth device profile (HL)
+ * subsystem of BTA, Broadcom Corp's Bluetooth application layer for mobile
+ * phones.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+#include "gki.h"
+#include "bd.h"
+#include "bta_hl_api.h"
+#include "bta_hl_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_hl_reg =
+{
+ bta_hl_hdl_event,
+ BTA_HlDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_HlEnable
+**
+** Description Enable the HL subsystems. This function must be
+** called before any other functions in the HL API are called.
+** When the enable operation is completed the callback function
+** will be called with an BTA_HL_CTRL_ENABLE_CFM_EVT event.
+**
+** Parameters p_cback - HL event call back function
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlEnable(tBTA_HL_CTRL_CBACK *p_ctrl_cback)
+{
+ tBTA_HL_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_HL, &bta_hl_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_HL_API_ENABLE *)GKI_getbuf(sizeof(tBTA_HL_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_ENABLE_EVT;
+ p_buf->p_cback = p_ctrl_cback;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlDisable
+**
+** Description Disable the HL subsystem.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_HL);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_HL_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlRegister
+**
+** Description Register an HDP application
+**
+** Parameters app_id - Application ID
+** p_reg_param - non-platform related parameters for the
+** HDP application
+** p_cback - HL event callback fucntion
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlRegister(UINT8 app_id,
+ tBTA_HL_REG_PARAM *p_reg_param,
+ tBTA_HL_CBACK *p_cback)
+{
+ tBTA_HL_API_REGISTER *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_REGISTER *)GKI_getbuf((UINT16)sizeof(tBTA_HL_API_REGISTER))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_REGISTER_EVT;
+ p_buf->app_id = app_id;
+ p_buf->sec_mask = (p_reg_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ p_buf->p_cback = p_cback;
+ if (p_reg_param->p_srv_name)
+ {
+ BCM_STRNCPY_S(p_buf->srv_name, sizeof(p_buf->srv_name),
+ p_reg_param->p_srv_name, BTA_SERVICE_NAME_LEN);
+ p_buf->srv_name[BTA_SERVICE_NAME_LEN] = '\0';
+ }
+ else
+ p_buf->srv_name[0]= '\0';
+
+ if (p_reg_param->p_srv_desp)
+ {
+ BCM_STRNCPY_S(p_buf->srv_desp, sizeof(p_buf->srv_desp),
+ p_reg_param->p_srv_desp, BTA_SERVICE_DESP_LEN);
+ p_buf->srv_desp[BTA_SERVICE_DESP_LEN]= '\0';
+ }
+ else
+ p_buf->srv_desp[0]= '\0';
+
+ if (p_reg_param->p_provider_name)
+ {
+ BCM_STRNCPY_S(p_buf->provider_name, sizeof(p_buf->provider_name),
+ p_reg_param->p_provider_name, BTA_PROVIDER_NAME_LEN);
+ p_buf->provider_name[BTA_PROVIDER_NAME_LEN]= '\0';
+ }
+ else
+ p_buf->provider_name[0]= '\0';
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlDeregister
+**
+** Description Deregister an HDP application
+**
+** Parameters app_handle - Application handle
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlDeregister(tBTA_HL_APP_HANDLE app_handle)
+{
+ tBTA_HL_API_DEREGISTER *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_DEREGISTER *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DEREGISTER)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_DEREGISTER_EVT;
+ p_buf->app_handle = app_handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_HlCchOpen
+**
+** Description Open a Control channel connection with the specified BD address
+**
+** Parameters app_handle - Application Handle
+** p_open_param - parameters for opening a control channel
+**
+** Returns void
+**
+** Note: The control PSM value is used to select which
+** HDP insatnce should be used in case the peer device support
+** multiple HDP instances. Also, if the control PSM value is zero
+** then the first HDP instance is used for the control channel setup
+*******************************************************************************/
+void BTA_HlCchOpen(tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_CCH_OPEN_PARAM *p_open_param)
+{
+ tBTA_HL_API_CCH_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_CCH_OPEN *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_CCH_OPEN)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_CCH_OPEN_EVT;
+ p_buf->app_handle = app_handle;
+ p_buf->sec_mask = (p_open_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ bdcpy(p_buf->bd_addr, p_open_param->bd_addr);
+ p_buf->ctrl_psm = p_open_param->ctrl_psm;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlCchClose
+**
+** Description Close a Control channel connection with the specified MCL
+** handle
+**
+** Parameters mcl_handle - MCL handle
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlCchClose(tBTA_HL_MCL_HANDLE mcl_handle)
+{
+ tBTA_HL_API_CCH_CLOSE *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_CCH_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_CCH_CLOSE)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_CCH_CLOSE_EVT;
+ p_buf->mcl_handle = mcl_handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlDchOpen
+**
+** Description Open a data channel connection with the specified DCH parameters
+**
+** Parameters mcl_handle - MCL handle
+** p_open_param - parameters for opening a data channel
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlDchOpen(tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_DCH_OPEN_PARAM *p_open_param)
+{
+ tBTA_HL_API_DCH_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_DCH_OPEN *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_OPEN)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_DCH_OPEN_EVT;
+ p_buf->mcl_handle = mcl_handle;
+ p_buf->ctrl_psm = p_open_param->ctrl_psm;
+ p_buf->local_mdep_id = p_open_param->local_mdep_id;
+ p_buf->peer_mdep_id = p_open_param->peer_mdep_id;
+ p_buf->local_cfg = p_open_param->local_cfg;
+ p_buf->sec_mask = (p_open_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlDchReconnect
+**
+** Description Reconnect a data channel with the specified MDL_ID
+**
+** Parameters mcl_handle - MCL handle
+*8 p_recon_param - parameters for reconnecting a data channel
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlDchReconnect(tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_DCH_RECONNECT_PARAM *p_recon_param)
+{
+ tBTA_HL_API_DCH_RECONNECT *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_DCH_RECONNECT *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_RECONNECT)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_DCH_RECONNECT_EVT;
+ p_buf->mcl_handle = mcl_handle;
+ p_buf->ctrl_psm = p_recon_param->ctrl_psm;
+ p_buf->mdl_id = p_recon_param->mdl_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlDchClose
+**
+** Description Close a data channel with the specified MDL handle
+**
+** Parameters mdl_handle - MDL handle
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlDchClose(tBTA_HL_MDL_HANDLE mdl_handle)
+{
+ tBTA_HL_API_DCH_CLOSE *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_DCH_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_CLOSE)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_DCH_CLOSE_EVT;
+ p_buf->mdl_handle = mdl_handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlDchAbort
+**
+** Description Abort the current data channel setup with the specified MCL
+** handle
+**
+** Parameters mcl_handle - MCL handle
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlDchAbort(tBTA_HL_MCL_HANDLE mcl_handle)
+{
+ tBTA_HL_API_DCH_ABORT *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_DCH_ABORT *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_ABORT)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_DCH_ABORT_EVT;
+ p_buf->mcl_handle = mcl_handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlSendData
+**
+** Description Send an APDU to the peer device
+**
+** Parameters mdl_handle - MDL handle
+** pkt_size - size of the data packet to be sent
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlSendData(tBTA_HL_MDL_HANDLE mdl_handle,
+ UINT16 pkt_size)
+{
+ tBTA_HL_API_SEND_DATA *p_buf = NULL;
+
+ if ((p_buf = (tBTA_HL_API_SEND_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_SEND_DATA)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_SEND_DATA_EVT;
+ p_buf->mdl_handle = mdl_handle;
+ p_buf->pkt_size = pkt_size;
+ bta_sys_sendmsg(p_buf);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlDeleteMdl
+**
+** Description Delete the specified MDL_ID within the specified MCL handle
+**
+** Parameters mcl_handle - MCL handle
+** mdl_id - MDL ID
+**
+** Returns void
+**
+** note: If mdl_id = 0xFFFF then this means to delete all MDLs
+** and this value can only be used with DeleteMdl request only
+** not other requests
+**
+*******************************************************************************/
+void BTA_HlDeleteMdl(tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_ID mdl_id )
+{
+ tBTA_HL_API_DELETE_MDL *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_DELETE_MDL *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DELETE_MDL)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_DELETE_MDL_EVT;
+ p_buf->mcl_handle = mcl_handle;
+ p_buf->mdl_id = mdl_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HlDchEchoTest
+**
+** Description Initiate an echo test with the specified MCL handle
+**
+** Parameters mcl_handle - MCL handle
+*8 p_echo_test_param - parameters for echo testing
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlDchEchoTest( tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_DCH_ECHO_TEST_PARAM *p_echo_test_param)
+{
+ tBTA_HL_API_DCH_ECHO_TEST *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_DCH_ECHO_TEST *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_ECHO_TEST)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_DCH_ECHO_TEST_EVT;
+ p_buf->mcl_handle = mcl_handle;
+ p_buf->ctrl_psm = p_echo_test_param->ctrl_psm;
+ p_buf->local_cfg = p_echo_test_param->local_cfg;
+ p_buf->pkt_size = p_echo_test_param->pkt_size;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_HlSdpQuery
+**
+** Description SDP query request for the specified BD address
+**
+** Parameters app_handle - application handle
+** bd_addr - BD address
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlSdpQuery(tBTA_HL_APP_HANDLE app_handle,
+ BD_ADDR bd_addr)
+{
+ tBTA_HL_API_SDP_QUERY *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_SDP_QUERY *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_SDP_QUERY)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_SDP_QUERY_EVT;
+ p_buf->app_handle = app_handle;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_HlDchCreateMdlRsp
+**
+** Description Set the Response and configuration values for the Create MDL
+** request
+**
+** Parameters mcl_handle - MCL handle
+** p_rsp_param - parameters specified whether the request should
+** be accepted or not and if it should be accepted
+** then it also specified the configuration response
+** value
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HlDchCreateRsp(tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_DCH_CREATE_RSP_PARAM *p_rsp_param)
+{
+ tBTA_HL_API_DCH_CREATE_RSP *p_buf;
+
+ if ((p_buf = (tBTA_HL_API_DCH_CREATE_RSP *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_CREATE_RSP)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HL_API_DCH_CREATE_RSP_EVT;
+ p_buf->mcl_handle = mcl_handle;
+ p_buf->mdl_id = p_rsp_param->mdl_id;
+ p_buf->local_mdep_id = p_rsp_param->local_mdep_id;
+ p_buf->rsp_code = p_rsp_param->rsp_code;
+ p_buf->cfg_rsp = p_rsp_param->cfg_rsp;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_ci.c b/bta/hl/bta_hl_ci.c
new file mode 100644
index 0000000..bd04b44
--- /dev/null
+++ b/bta/hl/bta_hl_ci.c
@@ -0,0 +1,171 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation file for the HeaLth device profile (HL)
+ * subsystem call-in functions.
+ *
+ ******************************************************************************/
+#include "bta_api.h"
+#include "btm_api.h"
+#include "bta_sys.h"
+#include "bta_hl_api.h"
+#include "bta_hl_co.h"
+#include "bta_hl_int.h"
+
+/*******************************************************************************
+**
+** Function bta_hl_ci_get_tx_data
+**
+** Description This function is called in response to the
+** bta_hl_co_get_tx_data call-out function.
+**
+** Parameters mdl_handle -MDL handle
+** status - BTA_MA_STATUS_OK if operation is successful
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_get_tx_data( tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_STATUS status,
+ UINT16 evt )
+{
+ tBTA_HL_CI_GET_PUT_DATA *p_evt;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG3("bta_hl_ci_get_tx_data mdl_handle=%d status=%d evt=%d\n",
+ mdl_handle, status, evt);
+#endif
+
+ if ((p_evt = (tBTA_HL_CI_GET_PUT_DATA *)GKI_getbuf(sizeof(tBTA_HL_CI_GET_PUT_DATA))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->mdl_handle = mdl_handle;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_ci_put_rx_data
+**
+** Description This function is called in response to the
+** bta_hl_co_put_rx_data call-out function.
+**
+** Parameters mdl_handle -MDL handle
+** status - BTA_MA_STATUS_OK if operation is successful
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_put_rx_data( tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_STATUS status,
+ UINT16 evt )
+{
+ tBTA_HL_CI_GET_PUT_DATA *p_evt;
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG3("bta_hl_ci_put_rx_data mdl_handle=%d status=%d evt=%d\n",
+ mdl_handle, status, evt);
+#endif
+
+ if ((p_evt = (tBTA_HL_CI_GET_PUT_DATA *)GKI_getbuf(sizeof(tBTA_HL_CI_GET_PUT_DATA))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->mdl_handle = mdl_handle;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_ci_get_echo_data
+**
+** Description This function is called in response to the
+** bta_hl_co_get_echo_data call-out function.
+**
+** Parameters mcl_handle -MCL handle
+** status - BTA_MA_STATUS_OK if operation is successful
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_get_echo_data( tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status,
+ UINT16 evt )
+{
+ tBTA_HL_CI_ECHO_DATA *p_evt;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG3("bta_hl_ci_get_echo_data mcl_handle=%d status=%d evt=%d\n",
+ mcl_handle, status, evt);
+#endif
+
+ if ((p_evt = (tBTA_HL_CI_ECHO_DATA *)GKI_getbuf(sizeof(tBTA_HL_CI_ECHO_DATA))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->mcl_handle = mcl_handle;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_ci_put_echo_data
+**
+** Description This function is called in response to the
+** bta_hl_co_put_echo_data call-out function.
+**
+** Parameters mcl_handle -MCL handle
+** status - BTA_MA_STATUS_OK if operation is successful
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_put_echo_data( tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status,
+ UINT16 evt )
+{
+ tBTA_HL_CI_ECHO_DATA *p_evt;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG3("bta_hl_ci_put_echo_data mcl_handle=%d status=%d evt=%d\n",
+ mcl_handle, status, evt);
+#endif
+
+ if ((p_evt = (tBTA_HL_CI_ECHO_DATA *)GKI_getbuf(sizeof(tBTA_HL_CI_ECHO_DATA))) != NULL)
+ {
+ p_evt->hdr.event = evt;
+ p_evt->mcl_handle = mcl_handle;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
diff --git a/bta/hl/bta_hl_int.h b/bta/hl/bta_hl_int.h
new file mode 100644
index 0000000..648eb2c
--- /dev/null
+++ b/bta/hl/bta_hl_int.h
@@ -0,0 +1,858 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1998-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private file for the message access equipment (MSE)
+ * subsystem.
+ *
+ ******************************************************************************/
+#ifndef BTA_HL_INT_H
+#define BTA_HL_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_hl_api.h"
+#include "bta_hl_co.h"
+#include "l2cdefs.h"
+
+
+typedef UINT16 (tBTA_HL_ALLOCATE_PSM) (void);
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+#ifndef BTA_HL_DISC_SIZE
+#define BTA_HL_DISC_SIZE 1600
+#endif
+#define BTA_HL_NUM_SRCH_ATTR 10
+#define BTA_HL_MIN_SDP_MDEP_LEN 7
+
+/* L2CAP defualt parameters */
+#define BTA_HL_L2C_TX_WIN_SIZE 10
+#define BTA_HL_L2C_MAX_TRANSMIT 32
+#define BTA_HL_L2C_RTRANS_TOUT 2000
+#define BTA_HL_L2C_MON_TOUT 12000
+#define BTA_HL_L2C_MPS 1017
+#define BTA_HL_L2C_USER_RX_POOL_ID L2CAP_DEFAULT_ERM_POOL_ID
+#define BTA_HL_L2C_USER_TX_POOL_ID L2CAP_DEFAULT_ERM_POOL_ID /* todo this should be based on data type */
+#define BTA_HL_L2C_FCR_RX_POOL_ID L2CAP_DEFAULT_ERM_POOL_ID
+#define BTA_HL_L2C_FCR_TX_POOL_ID L2CAP_DEFAULT_ERM_POOL_ID
+
+/* L2CAP FCS setting*/
+#define BTA_HL_MCA_USE_FCS MCA_FCS_USE
+#define BTA_HL_MCA_NO_FCS MCA_FCS_BYPASS
+#define BTA_HL_L2C_USE_FCS 1
+#define BTA_HL_L2C_NO_FCS 0
+#define BTA_HL_DEFAULT_SOURCE_FCS BTA_HL_L2C_USE_FCS
+
+/* SDP Operations */
+#define BTA_HL_SDP_OP_NONE 0
+#define BTA_HL_SDP_OP_CCH_INIT 1
+#define BTA_HL_SDP_OP_DCH_OPEN_INIT 2
+#define BTA_HL_SDP_OP_DCH_RECONNECT_INIT 3
+#define BTA_HL_SDP_OP_SDP_QUERY_NEW 4
+#define BTA_HL_SDP_OP_SDP_QUERY_CURRENT 5
+
+typedef UINT8 tBTA_HL_SDP_OPER;
+
+/* CCH Operations */
+#define BTA_HL_CCH_OP_NONE 0
+#define BTA_HL_CCH_OP_LOCAL_OPEN 1
+#define BTA_HL_CCH_OP_REMOTE_OPEN 2
+#define BTA_HL_CCH_OP_LOCAL_CLOSE 3
+#define BTA_HL_CCH_OP_REMOTE_CLOSE 4
+
+typedef UINT8 tBTA_HL_CCH_OPER;
+
+/* Pending DCH close operations when closing a CCH */
+#define BTA_HL_CCH_CLOSE_OP_DCH_NONE 0
+#define BTA_HL_CCH_CLOSE_OP_DCH_ABORT 1
+#define BTA_HL_CCH_CLOSE_OP_DCH_CLOSE 2
+typedef UINT8 tBTA_HL_CCH_CLOSE_DCH_OPER;
+
+/* DCH Operations */
+#define BTA_HL_DCH_OP_NONE 0
+#define BTA_HL_DCH_OP_REMOTE_CREATE 1
+#define BTA_HL_DCH_OP_LOCAL_OPEN 2
+#define BTA_HL_DCH_OP_REMOTE_OPEN 3
+#define BTA_HL_DCH_OP_LOCAL_CLOSE 4
+#define BTA_HL_DCH_OP_REMOTE_CLOSE 5
+#define BTA_HL_DCH_OP_LOCAL_DELETE 6
+#define BTA_HL_DCH_OP_REMOTE_DELETE 7
+#define BTA_HL_DCH_OP_LOCAL_RECONNECT 8
+#define BTA_HL_DCH_OP_REMOTE_RECONNECT 9
+#define BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST 10
+#define BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT 11
+
+typedef UINT8 tBTA_HL_DCH_OPER;
+
+/* Echo test Operations */
+#define BTA_HL_ECHO_OP_NONE 0
+#define BTA_HL_ECHO_OP_CI_GET_ECHO_DATA 1
+#define BTA_HL_ECHO_OP_SDP_INIT 2
+#define BTA_HL_ECHO_OP_MDL_CREATE_CFM 3
+#define BTA_HL_ECHO_OP_DCH_OPEN_CFM 4
+#define BTA_HL_ECHO_OP_LOOP_BACK 5
+#define BTA_HL_ECHO_OP_CI_PUT_ECHO_DATA 6
+#define BTA_HL_ECHO_OP_DCH_CLOSE_CFM 7
+#define BTA_HL_ECHO_OP_OPEN_IND 8
+#define BTA_HL_ECHO_OP_ECHO_PKT 9
+
+typedef UINT8 tBTA_HL_ECHO_OPER;
+
+/* abort status mask for abort_oper */
+
+#define BTA_HL_ABORT_NONE_MASK 0x00
+#define BTA_HL_ABORT_PENDING_MASK 0x01
+#define BTA_HL_ABORT_LOCAL_MASK 0x10
+#define BTA_HL_ABORT_REMOTE_MASK 0x20
+#define BTA_HL_ABORT_CCH_CLOSE_MASK 0x40
+
+/* call out mask for cout_oper */
+#define BTA_HL_CO_NONE_MASK 0x00
+#define BTA_HL_CO_GET_TX_DATA_MASK 0x01
+#define BTA_HL_CO_PUT_RX_DATA_MASK 0x02
+#define BTA_HL_CO_GET_ECHO_DATA_MASK 0x04
+#define BTA_HL_CO_PUT_ECHO_DATA_MASK 0x08
+
+typedef struct
+{
+ UINT16 mtu;
+ UINT8 fcs; /* '0' No FCS, otherwise '1' */
+} tBTA_HL_L2CAP_CFG_INFO;
+
+
+/* State Machine Events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_HL_CCH_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HL),
+ BTA_HL_CCH_SDP_OK_EVT,
+ BTA_HL_CCH_SDP_FAIL_EVT,
+ BTA_HL_MCA_CONNECT_IND_EVT,
+ BTA_HL_MCA_DISCONNECT_IND_EVT,
+ BTA_HL_CCH_CLOSE_EVT,
+ BTA_HL_CCH_CLOSE_CMPL_EVT,
+ BTA_HL_MCA_RSP_TOUT_IND_EVT,
+ /* DCH EVENT */
+ BTA_HL_DCH_SDP_INIT_EVT,
+ BTA_HL_DCH_OPEN_EVT,
+ BTA_HL_MCA_CREATE_IND_EVT,
+ BTA_HL_MCA_CREATE_CFM_EVT,
+ BTA_HL_MCA_OPEN_IND_EVT,
+
+ BTA_HL_MCA_OPEN_CFM_EVT,
+ BTA_HL_DCH_CLOSE_EVT,
+ BTA_HL_MCA_CLOSE_IND_EVT,
+ BTA_HL_MCA_CLOSE_CFM_EVT,
+ BTA_HL_API_SEND_DATA_EVT,
+
+ BTA_HL_MCA_RCV_DATA_EVT,
+ BTA_HL_DCH_CLOSE_CMPL_EVT,
+ BTA_HL_DCH_RECONNECT_EVT,
+ BTA_HL_DCH_SDP_FAIL_EVT,
+ BTA_HL_MCA_RECONNECT_IND_EVT,
+
+ BTA_HL_MCA_RECONNECT_CFM_EVT,
+ BTA_HL_DCH_CLOSE_ECHO_TEST_EVT,
+ BTA_HL_API_DCH_CREATE_RSP_EVT,
+ BTA_HL_DCH_ABORT_EVT,
+ BTA_HL_MCA_ABORT_IND_EVT,
+
+ BTA_HL_MCA_ABORT_CFM_EVT,
+ BTA_HL_MCA_CONG_CHG_EVT,
+ BTA_HL_CI_GET_TX_DATA_EVT,
+ BTA_HL_CI_PUT_RX_DATA_EVT,
+ BTA_HL_CI_GET_ECHO_DATA_EVT,
+ BTA_HL_DCH_ECHO_TEST_EVT,
+ BTA_HL_CI_PUT_ECHO_DATA_EVT,
+
+ /* these events are handled outside the state machine */
+ BTA_HL_API_ENABLE_EVT,
+ BTA_HL_API_DISABLE_EVT,
+ BTA_HL_API_REGISTER_EVT,
+ BTA_HL_API_DEREGISTER_EVT,
+ BTA_HL_API_CCH_OPEN_EVT,
+ BTA_HL_API_CCH_CLOSE_EVT,
+ BTA_HL_API_DCH_OPEN_EVT,
+ BTA_HL_API_DCH_RECONNECT_EVT,
+ BTA_HL_API_DCH_CLOSE_EVT,
+ BTA_HL_API_DELETE_MDL_EVT,
+ BTA_HL_API_DCH_ABORT_EVT,
+
+ BTA_HL_API_DCH_ECHO_TEST_EVT,
+ BTA_HL_API_SDP_QUERY_EVT,
+ BTA_HL_SDP_QUERY_OK_EVT,
+ BTA_HL_SDP_QUERY_FAIL_EVT,
+ BTA_HL_MCA_DELETE_IND_EVT,
+ BTA_HL_MCA_DELETE_CFM_EVT
+};
+typedef UINT16 tBTA_HL_INT_EVT;
+
+#define BTA_HL_DCH_EVT_MIN BTA_HL_DCH_SDP_INIT_EVT
+#define BTA_HL_DCH_EVT_MAX 0xFFFF
+
+
+/* state machine states */
+enum
+{
+ BTA_HL_CCH_IDLE_ST = 0, /* Idle */
+ BTA_HL_CCH_OPENING_ST, /* Opening a connection*/
+ BTA_HL_CCH_OPEN_ST, /* Connection is open */
+ BTA_HL_CCH_CLOSING_ST /* Closing is in progress */
+};
+typedef UINT8 tBTA_HL_CCH_STATE;
+
+enum
+{
+ BTA_HL_DCH_IDLE_ST = 0, /* Idle */
+ BTA_HL_DCH_OPENING_ST, /* Opening a connection*/
+ BTA_HL_DCH_OPEN_ST, /* Connection is open */
+ BTA_HL_DCH_CLOSING_ST /* Closing is in progress */
+};
+typedef UINT8 tBTA_HL_DCH_STATE;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_CTRL_CBACK *p_cback; /* pointer to control callback function */
+} tBTA_HL_API_ENABLE;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 app_id;
+ tBTA_HL_CBACK *p_cback; /* pointer to application callback function */
+ tBTA_HL_DEVICE_TYPE dev_type; /* sink, source or dual roles */
+ tBTA_SEC sec_mask; /* security mask for accepting conenction*/
+ char srv_name[BTA_SERVICE_NAME_LEN +1]; /* service name to be used in the SDP; null terminated*/
+ char srv_desp[BTA_SERVICE_DESP_LEN +1]; /* service description to be used in the SDP; null terminated */
+ char provider_name[BTA_PROVIDER_NAME_LEN +1]; /* provide name to be used in the SDP; null terminated */
+} tBTA_HL_API_REGISTER;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_API_DEREGISTER;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_APP_HANDLE app_handle;
+ UINT16 ctrl_psm;
+ BD_ADDR bd_addr; /* Address of peer device */
+ tBTA_SEC sec_mask; /* security mask for initiating connection*/
+} tBTA_HL_API_CCH_OPEN;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+} tBTA_HL_API_CCH_CLOSE;
+
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ UINT16 ctrl_psm;
+ tBTA_HL_MDEP_ID local_mdep_id; /* local MDEP ID */
+ tBTA_HL_MDEP_ID peer_mdep_id; /* peer mdep id */
+ tBTA_HL_DCH_CFG local_cfg;
+ tBTA_SEC sec_mask; /* security mask for initiating connection*/
+} tBTA_HL_API_DCH_OPEN;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ UINT16 ctrl_psm;
+ tBTA_HL_MDL_ID mdl_id;
+} tBTA_HL_API_DCH_RECONNECT;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MDL_HANDLE mdl_handle;
+} tBTA_HL_API_DCH_CLOSE;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_MDL_ID mdl_id;
+} tBTA_HL_API_DELETE_MDL;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+} tBTA_HL_API_DCH_ABORT;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ UINT16 pkt_size;
+} tBTA_HL_API_SEND_DATA;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ UINT16 ctrl_psm;
+ UINT16 pkt_size;
+ tBTA_HL_DCH_CFG local_cfg;
+} tBTA_HL_API_DCH_ECHO_TEST;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 app_idx;
+ UINT8 mcl_idx;
+ BOOLEAN release_mcl_cb;
+}tBTA_HL_CCH_SDP;
+
+
+/* MCA callback event parameters. */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_APP_HANDLE app_handle;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tMCA_CTRL mca_data;
+} tBTA_HL_MCA_EVT;
+
+
+/* MCA callback event parameters. */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 app_idx;
+ UINT8 mcl_idx;
+ UINT8 mdl_idx;
+ BT_HDR *p_pkt;
+} tBTA_HL_MCA_RCV_DATA_EVT;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 app_idx;
+ UINT8 mcl_idx;
+ UINT8 mdl_idx;
+}tBTA_HL_DCH_SDP;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_APP_HANDLE app_handle;
+ BD_ADDR bd_addr; /* Address of peer device */
+} tBTA_HL_API_SDP_QUERY;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_MDL_ID mdl_id;
+ tBTA_HL_MDEP_ID local_mdep_id;
+ tBTA_HL_DCH_CREATE_RSP rsp_code;
+ tBTA_HL_DCH_CFG cfg_rsp;
+} tBTA_HL_API_DCH_CREATE_RSP;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ tBTA_HL_STATUS status;
+} tBTA_HL_CI_GET_PUT_DATA;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_STATUS status;
+} tBTA_HL_CI_ECHO_DATA;
+
+/* union of all state machine event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_HL_API_ENABLE api_enable; /* data for BTA_MSE_API_ENABLE_EVT */
+ tBTA_HL_API_REGISTER api_reg;
+ tBTA_HL_API_DEREGISTER api_dereg;
+ tBTA_HL_API_CCH_OPEN api_cch_open;
+ tBTA_HL_API_CCH_CLOSE api_cch_close;
+ tBTA_HL_API_DCH_CREATE_RSP api_dch_create_rsp;
+ tBTA_HL_API_DCH_OPEN api_dch_open;
+ tBTA_HL_API_DCH_RECONNECT api_dch_reconnect;
+ tBTA_HL_API_DCH_CLOSE api_dch_close;
+ tBTA_HL_API_DELETE_MDL api_delete_mdl;
+ tBTA_HL_API_DCH_ABORT api_dch_abort;
+ tBTA_HL_API_SEND_DATA api_send_data;
+ tBTA_HL_API_DCH_ECHO_TEST api_dch_echo_test;
+ tBTA_HL_API_SDP_QUERY api_sdp_query;
+
+ tBTA_HL_CCH_SDP cch_sdp;
+ tBTA_HL_MCA_EVT mca_evt;
+ tBTA_HL_MCA_RCV_DATA_EVT mca_rcv_data_evt;
+ tBTA_HL_DCH_SDP dch_sdp; /* for DCH_OPEN_EVT and DCH_RECONNECT_EVT */
+ tBTA_HL_CI_GET_PUT_DATA ci_get_put_data;
+ tBTA_HL_CI_ECHO_DATA ci_get_put_echo_data;
+} tBTA_HL_DATA;
+
+
+typedef struct
+{
+ BOOLEAN in_use;
+ UINT16 mdl_id;
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ tBTA_HL_DCH_OPER dch_oper;
+ BOOLEAN intentional_close;
+ tBTA_HL_DCH_STATE dch_state;
+ UINT8 abort_oper;
+ UINT16 req_data_psm;
+ UINT16 max_rx_apdu_size;
+ UINT16 max_tx_apdu_size;
+ BT_HDR *p_tx_pkt;
+ BT_HDR *p_rx_pkt;
+ tBTA_HL_MDEP_ID local_mdep_id;
+ UINT8 local_mdep_cfg_idx;
+ tBTA_HL_DCH_CFG local_cfg;
+ tBTA_HL_DCH_CFG remote_cfg;
+ tBTA_HL_MDEP_ID peer_mdep_id;
+ UINT16 peer_data_type;
+ tBTA_HL_MDEP_ROLE peer_mdep_role;
+ tBTA_HL_DCH_MODE dch_mode;
+ tBTA_SEC sec_mask;
+ BOOLEAN is_the_first_reliable;
+ BOOLEAN delete_mdl;
+ UINT16 mtu;
+ tMCA_CHNL_CFG chnl_cfg;
+ BOOLEAN mdl_cfg_idx_included;
+ UINT8 mdl_cfg_idx;
+ UINT8 echo_oper;
+ BOOLEAN cong;
+ BOOLEAN close_pending;
+ UINT8 cout_oper;
+ BT_HDR *p_echo_tx_pkt;
+ BT_HDR *p_echo_rx_pkt;
+ tBTA_HL_STATUS ci_put_echo_data_status;
+}tBTA_HL_MDL_CB;
+
+typedef struct
+{
+ tBTA_HL_MDL_CB mdl[BTA_HL_NUM_MDLS_PER_MCL];
+ tBTA_HL_DELETE_MDL delete_mdl;
+ BOOLEAN in_use;
+ tBTA_HL_CCH_STATE cch_state;
+ UINT16 req_ctrl_psm;
+ UINT16 ctrl_psm;
+ UINT16 data_psm;
+ BD_ADDR bd_addr;
+ UINT16 cch_mtu;
+ UINT16 sec_mask;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tSDP_DISCOVERY_DB *p_db; /* pointer to discovery database */
+ tSDP_DISC_CMPL_CB *sdp_cback;
+ tBTA_HL_SDP_OPER sdp_oper;
+ BOOLEAN close_pending;
+ UINT8 sdp_mdl_idx;
+ tBTA_HL_SDP sdp;
+ UINT8 cch_oper;
+ BOOLEAN intentional_close;
+ BOOLEAN rsp_tout;
+ UINT8 timer_oper;
+ BOOLEAN echo_test;
+ UINT8 echo_mdl_idx;
+ UINT8 cch_close_dch_oper;
+}tBTA_HL_MCL_CB;
+
+typedef struct
+{
+ tBTA_HL_MCL_CB mcb[BTA_HL_NUM_MCLS]; /* application Control Blocks */
+ tBTA_HL_CBACK *p_cback; /* pointer to control callback function */
+ BOOLEAN in_use; /* this CB is in use*/
+ BOOLEAN deregistering;
+ UINT8 app_id;
+ UINT32 sdp_handle; /* SDP record handle */
+ tBTA_HL_SUP_FEATURE sup_feature;
+ tBTA_HL_MDL_CFG mdl_cfg[BTA_HL_NUM_MDL_CFGS];
+ tBTA_HL_DEVICE_TYPE dev_type;
+ tBTA_HL_APP_HANDLE app_handle;
+ UINT16 ctrl_psm; /* L2CAP PSM for the MCAP control channel */
+ UINT16 data_psm; /* L2CAP PSM for the MCAP data channel */
+ UINT16 sec_mask; /* Security mask for BTM_SetSecurityLevel() */
+
+ char srv_name[BTA_SERVICE_NAME_LEN +1]; /* service name to be used in the SDP; null terminated*/
+ char srv_desp[BTA_SERVICE_DESP_LEN +1]; /* service description to be used in the SDP; null terminated */
+ char provider_name[BTA_PROVIDER_NAME_LEN +1]; /* provide name to be used in the SDP; null terminated */
+
+ tMCA_CTRL_CBACK *p_mcap_cback; /* pointer to MCAP callback function */
+ tMCA_DATA_CBACK *p_data_cback;
+}tBTA_HL_APP_CB;
+
+
+typedef struct
+{
+ BOOLEAN in_use;
+ tBTA_HL_SDP_OPER sdp_oper;
+ UINT8 app_idx;
+ UINT8 mcl_idx;
+ UINT8 mdl_idx;
+}tBTA_HL_SDP_CB;
+
+typedef struct
+{
+ BOOLEAN in_use;
+ UINT8 app_idx;
+ UINT8 mcl_idx;
+}tBTA_HL_TIMER_CB;
+
+typedef struct
+{
+ tBTA_HL_APP_CB acb[BTA_HL_NUM_APPS]; /* HL Control Blocks */
+ tBTA_HL_CTRL_CBACK *p_ctrl_cback; /* pointer to control callback function */
+ BOOLEAN enable;
+ BOOLEAN disabling;
+
+ tBTA_HL_SDP_CB scb[BTA_HL_NUM_SDP_CBACKS];
+ tBTA_HL_TIMER_CB tcb[BTA_HL_NUM_TIMERS];
+ BOOLEAN enable_random_psm;
+ tBTA_HL_ALLOCATE_PSM *p_alloc_psm;
+}tBTA_HL_CB;
+
+/******************************************************************************
+** Configuration Definitions
+*******************************************************************************/
+/* Configuration structure */
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* HL control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_HL_CB bta_hl_cb;
+#else
+extern tBTA_HL_CB *bta_hl_cb_ptr;
+ #define bta_hl_cb (*bta_hl_cb_ptr)
+#endif
+
+#define BTA_HL_GET_CB_PTR() &(bta_hl_cb)
+#define BTA_HL_GET_APP_CB_PTR(app_idx) &(bta_hl_cb.acb[(app_idx)])
+#define BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx) &(bta_hl_cb.acb[(app_idx)].mcb[(mcl_idx)])
+#define BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx) &(bta_hl_cb.acb[(app_idx)].mcb[(mcl_idx)].mdl[mdl_idx])
+#define BTA_HL_GET_MDL_CFG_PTR(app_idx, item_idx) &(bta_hl_cb.acb[(app_idx)].mdl_cfg[(item_idx)])
+#define BTA_HL_GET_ECHO_CFG_PTR(app_idx) &(bta_hl_cb.acb[(app_idx)].sup_feature.echo_cfg)
+#define BTA_HL_GET_MDEP_CFG_PTR(app_idx, mdep_cfg_idx) &(bta_hl_cb.acb[(app_idx)].sup_feature.mdep[mdep_cfg_idx].mdep_cfg)
+#define BTA_HL_GET_DATA_CFG_PTR(app_idx, mdep_cfg_idx, data_cfg_idx) \
+ &(bta_hl_cb.acb[(app_idx)].sup_feature.mdep[mdep_cfg_idx].mdep_cfg.data_cfg[data_cfg_idx])
+#define BTA_HL_GET_BUF_PTR(p_pkt) ((UINT8 *)((UINT8 *) (p_pkt+1) + p_pkt->offset))
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /* main */
+ extern BOOLEAN bta_hl_hdl_event(BT_HDR *p_msg);
+ /* sdp */
+ extern BOOLEAN bta_hl_fill_sup_feature_list( const tSDP_DISC_ATTR *p_attr,
+ tBTA_HL_SUP_FEATURE_LIST_ELEM *p_list);
+
+ extern tBTA_HL_STATUS bta_hl_sdp_register (UINT8 app_idx);
+ extern tSDP_DISC_REC *bta_hl_find_sink_or_src_srv_class_in_db (const tSDP_DISCOVERY_DB *p_db,
+ const tSDP_DISC_REC *p_start_rec);
+
+ /* action routines */
+ extern void bta_hl_dch_ci_get_tx_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_ci_put_rx_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_ci_get_echo_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+
+ extern void bta_hl_dch_echo_test(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_ci_put_echo_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_send_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_sdp_fail(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_cong_change(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_reconnect_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_reconnect_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_reconnect(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_sdp_init(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_close_echo_test(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_create_rsp(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_rcv_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_close_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_close_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_close(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_delete_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+
+ extern void bta_hl_dch_mca_delete_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_delete(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_abort_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_abort_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_abort(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_open_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_open_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_create_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_create_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_mca_create(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_DATA *p_data);
+ extern void bta_hl_deallocate_spd_cback(UINT8 sdp_cback_idx);
+ extern tSDP_DISC_CMPL_CB *bta_hl_allocate_spd_cback(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx,
+ UINT8 *p_sdp_cback_idx);
+ extern tBTA_HL_STATUS bta_hl_init_sdp(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx);
+ extern void bta_hl_cch_sdp_init(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+ extern void bta_hl_cch_mca_open(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+ extern void bta_hl_cch_mca_close(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+ extern void bta_hl_cch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+ extern void bta_hl_cch_mca_disconnect(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+ extern void bta_hl_cch_mca_rsp_tout(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+ extern void bta_hl_cch_mca_connect(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+
+ /* State machine drivers */
+ extern void bta_hl_cch_sm_execute(UINT8 inst_idx, UINT8 mcl_idx,
+ UINT16 event, tBTA_HL_DATA *p_data);
+ extern void bta_hl_dch_sm_execute(UINT8 inst_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ UINT16 event, tBTA_HL_DATA *p_data);
+ /* MCAP callback functions */
+ extern void bta_hl_mcap_ctrl_cback(tMCA_HANDLE handle, tMCA_CL mcl, UINT8 event,
+ tMCA_CTRL *p_data);
+
+ extern void bta_hl_mcap_data_cback(tMCA_DL mdl, BT_HDR *p_pkt);
+
+ /* utility functions */
+ extern BOOLEAN bta_hl_set_ctrl_psm_for_dch(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx, UINT16 ctrl_psm);
+ extern BOOLEAN bta_hl_find_sdp_idx_using_ctrl_psm(tBTA_HL_SDP *p_sdp,
+ UINT16 ctrl_psm,
+ UINT8 *p_sdp_idx);
+ extern UINT8 bta_hl_set_user_tx_pool_id(UINT16 max_tx_size);
+ extern UINT8 bta_hl_set_user_rx_pool_id(UINT16 mtu);
+ extern UINT8 bta_hl_set_tx_win_size(UINT16 mtu, UINT16 mps);
+ extern UINT16 bta_hl_set_mps(UINT16 mtu);
+ extern void bta_hl_clean_mdl_cb(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx);
+ extern BT_HDR * bta_hl_get_buf(UINT16 data_size);
+ extern BOOLEAN bta_hl_find_service_in_db( UINT8 app_idx, UINT8 mcl_idx,
+ UINT16 service_uuid,
+ tSDP_DISC_REC **pp_rec );
+ extern UINT16 bta_hl_get_service_uuids(UINT8 sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx );
+ extern BOOLEAN bta_hl_find_echo_cfg_rsp(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdep_idx, UINT8 cfg,
+ UINT8 *p_cfg_rsp);
+ extern BOOLEAN bta_hl_validate_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ UINT8 cfg);
+ extern BOOLEAN bta_hl_find_cch_cb_indexes(tBTA_HL_DATA *p_msg,
+ UINT8 *p_app_idx,
+ UINT8 *p_mcl_idx);
+ extern BOOLEAN bta_hl_find_dch_cb_indexes(tBTA_HL_DATA *p_msg,
+ UINT8 *p_app_idx,
+ UINT8 *p_mcl_idx,
+ UINT8 *p_mdl_idx);
+ extern UINT16 bta_hl_allocate_mdl_id(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx );
+ extern BOOLEAN bta_hl_find_mdl_idx_using_handle(tBTA_HL_MDL_HANDLE mdl_handle,
+ UINT8 *p_app_idx, UINT8 *p_mcl_idx,
+ UINT8 *p_mdl_idx);
+ extern BOOLEAN bta_hl_find_mdl_idx(UINT8 app_idx, UINT8 mcl_idx, UINT16 mdl_id,
+ UINT8 *p_mdl_idx);
+ extern BOOLEAN bta_hl_find_an_active_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 *p_mdl_idx);
+ extern BOOLEAN bta_hl_find_dch_setup_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 *p_mdl_idx);
+ extern BOOLEAN bta_hl_find_an_in_use_mcl_idx(UINT8 app_idx,
+ UINT8 *p_mcl_idx);
+ extern BOOLEAN bta_hl_find_an_in_use_app_idx(UINT8 *p_app_idx);
+ extern BOOLEAN bta_hl_find_app_idx(UINT8 app_id, UINT8 *p_app_idx);
+ extern BOOLEAN bta_hl_find_app_idx_using_handle(tBTA_HL_APP_HANDLE app_handle,
+ UINT8 *p_app_idx);
+ extern BOOLEAN bta_hl_find_mcl_idx_using_handle( tBTA_HL_MCL_HANDLE mcl_handle,
+ UINT8 *p_app_idx, UINT8 *p_mcl_idx);
+ extern BOOLEAN bta_hl_find_mcl_idx(UINT8 app_idx, BD_ADDR p_bd_addr, UINT8 *p_mcl_idx);
+ extern BOOLEAN bta_hl_is_the_first_reliable_existed(UINT8 app_idx, UINT8 mcl_idx );
+ extern BOOLEAN bta_hl_find_non_active_mdl_cfg(UINT8 app_idx, UINT8 start_mdl_cfg_idx,
+ UINT8 *p_mdl_cfg_idx);
+ extern BOOLEAN bta_hl_find_avail_mdl_cfg_idx(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 *p_mdl_cfg_idx);
+ extern BOOLEAN bta_hl_find_mdl_cfg_idx(UINT8 app_idx, UINT8 mcl_idx,
+ tBTA_HL_MDL_ID mdl_id, UINT8 *p_mdl_cfg_idx);
+ extern BOOLEAN bta_hl_get_cur_time(UINT8 app_idx, UINT8 *p_cur_time);
+ extern void bta_hl_sort_cfg_time_idx(UINT8 app_idx, UINT8 *a, UINT8 n);
+ extern void bta_hl_compact_mdl_cfg_time(UINT8 app_idx);
+ extern BOOLEAN bta_hl_is_mdl_exsit_in_mcl(UINT8 app_idx, BD_ADDR bd_addr,
+ tBTA_HL_MDL_ID mdl_id);
+ extern BOOLEAN bta_hl_delete_mdl_cfg(UINT8 app_idx, BD_ADDR bd_addr,
+ tBTA_HL_MDL_ID mdl_id);
+ extern BOOLEAN bta_hl_is_mdl_value_valid(tBTA_HL_MDL_ID mdl_id);
+ extern BOOLEAN bta_hl_find_mdep_cfg_idx(UINT8 app_idx,
+ tBTA_HL_MDEP_ID local_mdep_id, UINT8 *p_mdep_cfg_idx);
+ extern void bta_hl_find_rxtx_apdu_size(UINT8 app_idx, UINT8 mdep_cfg_idx,
+ UINT16 *p_rx_apu_size,
+ UINT16 *p_tx_apu_size);
+ extern BOOLEAN bta_hl_validate_peer_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_MDEP_ID peer_mdep_id,
+ tBTA_HL_MDEP_ROLE peer_mdep_role,
+ UINT8 sdp_idx);
+ extern tBTA_HL_STATUS bta_hl_chk_local_cfg(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdep_cfg_idx,
+ tBTA_HL_DCH_CFG local_cfg);
+
+ extern BOOLEAN bta_hl_validate_reconnect_params(UINT8 app_idx, UINT8 mcl_idx,
+ tBTA_HL_API_DCH_RECONNECT *p_reconnect,
+ UINT8 *p_mdep_cfg_idx, UINT8 *p_mdl_cfg_idx);
+ extern BOOLEAN bta_hl_find_avail_mcl_idx(UINT8 app_idx, UINT8 *p_mcl_idx);
+ extern BOOLEAN bta_hl_find_avail_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 *p_mdl_idx);
+ extern BOOLEAN bta_hl_is_a_duplicate_id(UINT8 app_id);
+ extern BOOLEAN bta_hl_find_avail_app_idx(UINT8 *p_idx);
+ extern tBTA_HL_STATUS bta_hl_app_registration(UINT8 app_idx);
+ extern void bta_hl_discard_data(UINT16 event, tBTA_HL_DATA *p_data);
+ extern void bta_hl_save_mdl_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx );
+ extern void bta_hl_set_dch_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx, tBTA_HL_DATA *p_data);
+ extern BOOLEAN bta_hl_get_l2cap_cfg(tBTA_HL_MDL_HANDLE mdl_hnd, tBTA_HL_L2CAP_CFG_INFO *p_cfg);
+ extern BOOLEAN bta_hl_validate_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx);
+ extern BOOLEAN bta_hl_is_cong_on(UINT8 app_id, BD_ADDR bd_addr, tBTA_HL_MDL_ID mdl_id);
+ extern void bta_hl_check_cch_close(UINT8 app_idx, UINT8 mcl_idx,
+ tBTA_HL_DATA *p_data, BOOLEAN check_dch_setup);
+ extern void bta_hl_clean_app(UINT8 app_idx);
+ extern void bta_hl_check_deregistration(UINT8 app_idx, tBTA_HL_DATA *p_data );
+ extern void bta_hl_check_disable(tBTA_HL_DATA *p_data );
+ extern void bta_hl_build_abort_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle);
+ extern void bta_hl_build_abort_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status);
+ extern void bta_hl_build_dch_close_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_STATUS status);
+ extern void bta_hl_build_dch_close_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle,
+ BOOLEAN intentional);
+ extern void bta_hl_build_send_data_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_STATUS status );
+ extern void bta_hl_build_rcv_data_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle);
+ extern void bta_hl_build_cch_open_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ BD_ADDR bd_addr,
+ tBTA_HL_STATUS status );
+ extern void bta_hl_build_cch_open_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ BD_ADDR bd_addr);
+ extern void bta_hl_build_cch_close_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status );
+ extern void bta_hl_build_cch_close_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ BOOLEAN intentional);
+
+ extern void bta_hl_build_dch_open_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_MDEP_ID local_mdep_id,
+ tBTA_HL_MDL_ID mdl_id,
+ tBTA_HL_DCH_MODE dch_mode,
+ BOOLEAN first_reliable,
+ UINT16 mtu,
+ tBTA_HL_STATUS status);
+
+ extern void bta_hl_build_delete_mdl_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_ID mdl_id,
+ tBTA_HL_STATUS status);
+ extern void bta_hl_build_echo_test_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status );
+ extern void bta_hl_build_sdp_query_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ BD_ADDR bd_addr,
+ tBTA_HL_SDP *p_sdp,
+ tBTA_HL_STATUS status);
+
+#if (BTA_HL_DEBUG == TRUE)
+ extern char *bta_hl_status_code(tBTA_HL_STATUS status);
+ extern char *bta_hl_evt_code(tBTA_HL_INT_EVT evt_code);
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif /* BTA_MSE_INT_H */
+
+
diff --git a/bta/hl/bta_hl_main.c b/bta/hl/bta_hl_main.c
new file mode 100644
index 0000000..afac4c3
--- /dev/null
+++ b/bta/hl/bta_hl_main.c
@@ -0,0 +1,1920 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1998-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the HeaLth device profile main functions and state
+ * machine.
+ *
+ ******************************************************************************/
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+
+
+#include "bta_hl_api.h"
+#include "bta_hl_int.h"
+#include "gki.h"
+#include "utl.h"
+#include "bd.h"
+#include "l2c_api.h"
+#include "mca_defs.h"
+
+
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+static char *bta_hl_cch_state_code(tBTA_HL_CCH_STATE state_code);
+static char *bta_hl_dch_state_code(tBTA_HL_DCH_STATE state_code);
+#endif
+
+extern UINT16 L2CA_AllocateRandomPsm(void);
+extern UINT16 L2CA_AllocatePsm(void);
+/*****************************************************************************
+** DCH State Table
+*****************************************************************************/
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+/* state machine action enumeration list for DCH */
+/* The order of this enumeration must be the same as bta_hl_dch_act_tbl[] */
+enum
+{
+ BTA_HL_DCH_MCA_CREATE,
+ BTA_HL_DCH_MCA_CREATE_CFM,
+ BTA_HL_DCH_MCA_CREATE_IND,
+ BTA_HL_DCH_MCA_OPEN_CFM,
+ BTA_HL_DCH_MCA_OPEN_IND,
+ BTA_HL_DCH_MCA_CLOSE,
+ BTA_HL_DCH_MCA_CLOSE_CFM,
+ BTA_HL_DCH_MCA_CLOSE_IND,
+ BTA_HL_DCH_CLOSE_CMPL,
+ BTA_HL_DCH_MCA_RCV_DATA,
+
+ BTA_HL_DCH_SDP_INIT,
+ BTA_HL_DCH_MCA_RECONNECT,
+ BTA_HL_DCH_MCA_RECONNECT_IND,
+ BTA_HL_DCH_MCA_RECONNECT_CFM,
+ BTA_HL_DCH_CLOSE_ECHO_TEST,
+ BTA_HL_DCH_CREATE_RSP,
+ BTA_HL_DCH_MCA_ABORT,
+ BTA_HL_DCH_MCA_ABORT_IND,
+ BTA_HL_DCH_MCA_ABORT_CFM,
+ BTA_HL_DCH_MCA_CONG_CHANGE,
+
+ BTA_HL_DCH_SDP_FAIL,
+ BTA_HL_DCH_SEND_DATA,
+ BTA_HL_DCH_CI_GET_TX_DATA,
+ BTA_HL_DCH_CI_PUT_RX_DATA,
+ BTA_HL_DCH_CI_GET_ECHO_DATA,
+ BTA_HL_DCH_ECHO_TEST,
+ BTA_HL_DCH_CI_PUT_ECHO_DATA,
+ BTA_HL_DCH_IGNORE
+};
+
+typedef void (*tBTA_HL_DCH_ACTION)(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx, tBTA_HL_DATA *p_data);
+
+static const tBTA_HL_DCH_ACTION bta_hl_dch_action[] =
+{
+ bta_hl_dch_mca_create,
+ bta_hl_dch_mca_create_cfm,
+ bta_hl_dch_mca_create_ind,
+ bta_hl_dch_mca_open_cfm,
+ bta_hl_dch_mca_open_ind,
+ bta_hl_dch_mca_close,
+ bta_hl_dch_mca_close_cfm,
+ bta_hl_dch_mca_close_ind,
+ bta_hl_dch_close_cmpl,
+ bta_hl_dch_mca_rcv_data,
+
+ bta_hl_dch_sdp_init,
+ bta_hl_dch_mca_reconnect,
+ bta_hl_dch_mca_reconnect_ind,
+ bta_hl_dch_mca_reconnect_cfm,
+ bta_hl_dch_close_echo_test,
+ bta_hl_dch_create_rsp,
+ bta_hl_dch_mca_abort,
+ bta_hl_dch_mca_abort_ind,
+ bta_hl_dch_mca_abort_cfm,
+ bta_hl_dch_mca_cong_change,
+
+ bta_hl_dch_sdp_fail,
+ bta_hl_dch_send_data,
+ bta_hl_dch_ci_get_tx_data,
+ bta_hl_dch_ci_put_rx_data,
+ bta_hl_dch_ci_get_echo_data,
+ bta_hl_dch_echo_test,
+ bta_hl_dch_ci_put_echo_data,
+};
+
+
+/* state table information */
+#define BTA_HL_DCH_ACTIONS 1 /* number of actions */
+#define BTA_HL_DCH_ACTION_COL 0 /* position of action */
+#define BTA_HL_DCH_NEXT_STATE 1 /* position of next state */
+#define BTA_HL_DCH_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_hl_dch_st_idle[][BTA_HL_DCH_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_HL_DCH_SDP_INIT_EVT */ {BTA_HL_DCH_SDP_INIT, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_OPEN_EVT */ {BTA_HL_DCH_MCA_CREATE, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CREATE_IND_EVT */ {BTA_HL_DCH_MCA_CREATE_IND, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CREATE_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_OPEN_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+
+/* BTA_HL_MCA_OPEN_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_CLOSE_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_CLOSE_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_CLOSE_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_API_SEND_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+
+/* BTA_HL_MCA_RCV_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_CLOSE_CMPL_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_RECONNECT_EVT */ {BTA_HL_DCH_MCA_RECONNECT, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_SDP_FAIL_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_RECONNECT_IND_EVT*/ {BTA_HL_DCH_MCA_RECONNECT_IND, BTA_HL_DCH_OPENING_ST},
+
+/* BTA_HL_MCA_RECONNECT_CFM_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_CLOSE_ECHO_TEST_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_API_DCH_CREATE_RSP_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_ABORT_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_ABORT_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+
+/* BTA_HL_MCA_ABORT_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_CONG_CHG_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_CI_GET_TX_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_CI_PUT_RX_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_CI_GET_ECHO_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_ECHO_TEST_EVT */ {BTA_HL_DCH_ECHO_TEST, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_PUT_ECHO_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST}
+};
+
+/* state table for opening state */
+static const UINT8 bta_hl_dch_st_opening[][BTA_HL_DCH_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_HL_DCH_SDP_INIT_EVT */ {BTA_HL_DCH_SDP_INIT, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_OPEN_EVT */ {BTA_HL_DCH_MCA_CREATE, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CREATE_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CREATE_CFM_EVT */ {BTA_HL_DCH_MCA_CREATE_CFM, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_OPEN_IND_EVT */ {BTA_HL_DCH_MCA_OPEN_IND, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_OPEN_CFM_EVT */ {BTA_HL_DCH_MCA_OPEN_CFM, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CLOSE_IND_EVT */ {BTA_HL_DCH_MCA_CLOSE_IND, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_CFM_EVT */ {BTA_HL_DCH_MCA_CLOSE_CFM, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_SEND_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+
+/* BTA_HL_MCA_RCV_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_CMPL_EVT */ {BTA_HL_DCH_CLOSE_CMPL, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_RECONNECT_EVT */ {BTA_HL_DCH_MCA_RECONNECT, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_SDP_FAIL_EVT */ {BTA_HL_DCH_SDP_FAIL, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_RECONNECT_IND_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_RECONNECT_CFM_EVT*/ {BTA_HL_DCH_MCA_RECONNECT_CFM, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_CLOSE_ECHO_TEST_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_API_DCH_CREATE_RSP_EVT */ {BTA_HL_DCH_CREATE_RSP, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_ABORT_EVT */ {BTA_HL_DCH_MCA_ABORT, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_ABORT_IND_EVT */ {BTA_HL_DCH_MCA_ABORT_IND, BTA_HL_DCH_OPENING_ST},
+
+/* BTA_HL_MCA_ABORT_CFM_EVT */ {BTA_HL_DCH_MCA_ABORT_CFM, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CONG_CHG_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_GET_TX_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_PUT_RX_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_GET_ECHO_DATA_EVT */ {BTA_HL_DCH_CI_GET_ECHO_DATA, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_ECHO_TEST_EVT */ {BTA_HL_DCH_ECHO_TEST, BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_PUT_ECHO_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPENING_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_hl_dch_st_open[][BTA_HL_DCH_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_HL_DCH_SDP_INIT_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_OPEN_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_CREATE_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_CREATE_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_OPEN_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_OPEN_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_EVT */ {BTA_HL_DCH_MCA_CLOSE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_IND_EVT */ {BTA_HL_DCH_MCA_CLOSE_IND, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_CFM_EVT */ {BTA_HL_DCH_MCA_CLOSE_CFM, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_SEND_DATA_EVT */ {BTA_HL_DCH_SEND_DATA, BTA_HL_DCH_OPEN_ST},
+
+/* BTA_HL_MCA_RCV_DATA_EVT */ {BTA_HL_DCH_MCA_RCV_DATA, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_CMPL_EVT */ {BTA_HL_DCH_CLOSE_CMPL, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_RECONNECT_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_SDP_FAIL_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_RECONNECT_IND_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_RECONNECT_CFM_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_ECHO_TEST_EVT*/ {BTA_HL_DCH_CLOSE_ECHO_TEST, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_DCH_CREATE_RSP_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_ABORT_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_ABORT_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+
+/* BTA_HL_DCH_ABORT_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_CONG_CHG_EVT */ {BTA_HL_DCH_MCA_CONG_CHANGE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_CI_GET_TX_DATA_EVT */ {BTA_HL_DCH_CI_GET_TX_DATA, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_CI_PUT_RX_DATA_EVT */ {BTA_HL_DCH_CI_PUT_RX_DATA, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_CI_GET_ECHO_DATA_EVT */ {BTA_HL_DCH_CI_GET_ECHO_DATA, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_ECHO_TEST_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_CI_PUT_ECHO_DATA_EVT */ {BTA_HL_DCH_CI_PUT_ECHO_DATA, BTA_HL_DCH_OPEN_ST}
+};
+
+
+/* state table for closing state */
+static const UINT8 bta_hl_dch_st_closing[][BTA_HL_DCH_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_HL_DCH_SDP_INIT_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_OPEN_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CREATE_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CREATE_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_OPEN_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_OPEN_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_CLOSE_EVT */ {BTA_HL_DCH_MCA_CLOSE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_CFM_EVT */ {BTA_HL_DCH_MCA_CLOSE_CFM, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_SEND_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+
+/* BTA_HL_MCA_RCV_DATA_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_CLOSE_CMPL_EVT */ {BTA_HL_DCH_CLOSE_CMPL, BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_RECONNECT_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_SDP_FAIL_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_RECONNECT_IND_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_RECONNECT_CFM_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_CLOSE_ECHO_TEST_EVT*/ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_DCH_CREATE_RSP_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_ABORT_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_ABORT_IND_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+
+/* BTA_HL_DCH_ABORT_CFM_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CONG_CHG_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_CI_GET_TX_DATA_EVT */ {BTA_HL_DCH_CI_GET_TX_DATA, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_CI_PUT_RX_DATA_EVT */ {BTA_HL_DCH_CI_PUT_RX_DATA, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_CI_GET_ECHO_DATA_EVT */ {BTA_HL_DCH_CI_GET_ECHO_DATA, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_ECHO_TEST_EVT */ {BTA_HL_DCH_IGNORE, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_CI_PUT_ECHO_DATA_EVT */ {BTA_HL_DCH_CI_PUT_ECHO_DATA, BTA_HL_DCH_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_HL_DCH_ST_TBL)[BTA_HL_DCH_NUM_COLS];
+
+/* state table */
+const tBTA_HL_DCH_ST_TBL bta_hl_dch_st_tbl[] =
+{
+ bta_hl_dch_st_idle,
+ bta_hl_dch_st_opening,
+ bta_hl_dch_st_open,
+ bta_hl_dch_st_closing
+};
+
+/*****************************************************************************
+** CCH State Table
+*****************************************************************************/
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+/* state machine action enumeration list for CCH */
+enum
+{
+ BTA_HL_CCH_SDP_INIT,
+ BTA_HL_CCH_MCA_OPEN,
+ BTA_HL_CCH_MCA_CLOSE,
+ BTA_HL_CCH_CLOSE_CMPL,
+ BTA_HL_CCH_MCA_CONNECT,
+ BTA_HL_CCH_MCA_DISCONNECT,
+ BTA_HL_CCH_MCA_RSP_TOUT,
+ BTA_HL_CCH_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_HL_CCH_ACTION)(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+
+/* action function list for MAS */
+const tBTA_HL_CCH_ACTION bta_hl_cch_action[] =
+{
+ bta_hl_cch_sdp_init,
+ bta_hl_cch_mca_open,
+ bta_hl_cch_mca_close,
+ bta_hl_cch_close_cmpl,
+ bta_hl_cch_mca_connect,
+ bta_hl_cch_mca_disconnect,
+ bta_hl_cch_mca_rsp_tout
+};
+
+
+/* state table information */
+#define BTA_HL_CCH_ACTIONS 1 /* number of actions */
+#define BTA_HL_CCH_NEXT_STATE 1 /* position of next state */
+#define BTA_HL_CCH_NUM_COLS 2 /* number of columns in state tables */
+
+
+/* state table for MAS idle state */
+static const UINT8 bta_hl_cch_st_idle[][BTA_HL_CCH_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_HL_CCH_OPEN_EVT */ {BTA_HL_CCH_SDP_INIT, BTA_HL_CCH_OPENING_ST},
+/* BTA_HL_CCH_SDP_OK_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_SDP_FAIL_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT */ {BTA_HL_CCH_MCA_CONNECT, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_CLOSE_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_IDLE_ST}
+};
+
+/* state table for obex/rfcomm connection state */
+static const UINT8 bta_hl_cch_st_opening[][BTA_HL_CCH_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_HL_CCH_OPEN_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_OPENING_ST},
+/* BTA_HL_CCH_SDP_OK_EVT */ {BTA_HL_CCH_MCA_OPEN, BTA_HL_CCH_OPENING_ST},
+/* BTA_HL_CCH_SDP_FAIL_EVT */ {BTA_HL_CCH_CLOSE_CMPL, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT */ {BTA_HL_CCH_MCA_CONNECT, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_MCA_DISCONNECT, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_EVT */ {BTA_HL_CCH_MCA_CLOSE, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT */ {BTA_HL_CCH_CLOSE_CMPL, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_RSP_TOUT_IND_EVT */ {BTA_HL_CCH_MCA_RSP_TOUT, BTA_HL_CCH_CLOSING_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_hl_cch_st_open[][BTA_HL_CCH_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_HL_CCH_OPEN_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_CCH_SDP_OK_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_CCH_SDP_FAIL_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_MCA_DISCONNECT, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_EVT */ {BTA_HL_CCH_MCA_CLOSE, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_RSP_TOUT_IND_EVT */ {BTA_HL_CCH_MCA_RSP_TOUT, BTA_HL_CCH_CLOSING_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_hl_cch_st_closing[][BTA_HL_CCH_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_HL_CCH_OPEN_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_SDP_OK_EVT */ {BTA_HL_CCH_CLOSE_CMPL, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_SDP_FAIL_EVT */ {BTA_HL_CCH_CLOSE_CMPL, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT */ {BTA_HL_CCH_MCA_CONNECT, BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_MCA_DISCONNECT, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_EVT */ {BTA_HL_CCH_MCA_CLOSE, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT */ {BTA_HL_CCH_CLOSE_CMPL, BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_RSP_TOUT_IND_EVT */ {BTA_HL_CCH_IGNORE, BTA_HL_CCH_CLOSING_ST}
+};
+
+/* type for state table CCH */
+typedef const UINT8 (*tBTA_HL_CCH_ST_TBL)[BTA_HL_CCH_NUM_COLS];
+
+/* MAS state table */
+const tBTA_HL_CCH_ST_TBL bta_hl_cch_st_tbl[] =
+{
+ bta_hl_cch_st_idle,
+ bta_hl_cch_st_opening,
+ bta_hl_cch_st_open,
+ bta_hl_cch_st_closing
+};
+
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* HL control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_HL_CB bta_hl_cb;
+#endif
+
+
+/*******************************************************************************
+**
+** Function bta_hl_cch_sm_execute
+**
+** Description State machine event handling function for CCH
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_cch_sm_execute(UINT8 app_idx, UINT8 mcl_idx,
+ UINT16 event, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_CCH_ST_TBL state_table;
+ UINT8 action;
+ int i;
+ tBTA_HL_MCL_CB *p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ tBTA_HL_CCH_STATE in_state = p_cb->cch_state;
+ UINT16 cur_evt = event;
+ APPL_TRACE_DEBUG3("HDP CCH Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ bta_hl_cch_state_code(in_state),
+ bta_hl_evt_code(cur_evt));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_hl_cch_st_tbl[p_cb->cch_state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->cch_state = state_table[event][BTA_HL_CCH_NEXT_STATE];
+
+ for (i = 0; i < BTA_HL_CCH_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_HL_CCH_IGNORE)
+ {
+ (*bta_hl_cch_action[action])(app_idx, mcl_idx, p_data);
+ }
+ else
+ {
+ /* discard HDP data */
+ bta_hl_discard_data(p_data->hdr.event, p_data);
+ break;
+ }
+ }
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ if (in_state != p_cb->cch_state)
+ {
+ APPL_TRACE_DEBUG3("HL CCH State Change: [%s] -> [%s] after [%s]",
+ bta_hl_cch_state_code(in_state),
+ bta_hl_cch_state_code(p_cb->cch_state),
+ bta_hl_evt_code(cur_evt));
+ }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_sm_execute
+**
+** Description State machine event handling function for DCH
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_dch_sm_execute(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ UINT16 event, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_DCH_ST_TBL state_table;
+ UINT8 action;
+ int i;
+ tBTA_HL_MDL_CB *p_cb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ tBTA_HL_DCH_STATE in_state = p_cb->dch_state;
+ UINT16 cur_evt = event;
+ APPL_TRACE_DEBUG3("HDP DCH Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ bta_hl_dch_state_code(in_state),
+ bta_hl_evt_code(cur_evt));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_hl_dch_st_tbl[p_cb->dch_state];
+ event -= BTA_HL_DCH_EVT_MIN;
+
+ /* set next state */
+ p_cb->dch_state = state_table[event][BTA_HL_DCH_NEXT_STATE];
+
+ for (i = 0; i < BTA_HL_DCH_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_HL_DCH_IGNORE)
+ {
+ (*bta_hl_dch_action[action])(app_idx, mcl_idx, mdl_idx, p_data);
+ }
+ else
+ {
+ /* discard mas data */
+ bta_hl_discard_data(p_data->hdr.event, p_data);
+ break;
+ }
+ }
+
+
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ if (in_state != p_cb->dch_state)
+ {
+ APPL_TRACE_DEBUG3("HL DCH State Change: [%s] -> [%s] after [%s]",
+ bta_hl_dch_state_code(in_state),
+ bta_hl_dch_state_code(p_cb->dch_state),
+ bta_hl_evt_code(cur_evt));
+ }
+#endif
+}
+/*******************************************************************************
+**
+** Function bta_hl_api_enable
+**
+** Description Process the API enable request to enable the HL subsystem
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_enable(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_CTRL evt_data;
+
+ /* If already enabled then reject this request */
+ if (p_cb->enable)
+ {
+ APPL_TRACE_ERROR0("HL is already enabled");
+ evt_data.enable_cfm.status = BTA_HL_STATUS_FAIL;
+ if (p_data->api_enable.p_cback)
+ p_data->api_enable.p_cback(BTA_HL_CTRL_ENABLE_CFM_EVT, (tBTA_HL_CTRL *) &evt_data);
+ return;
+ }
+
+ /* Done with checking. now perform the enable oepration*/
+ /* initialize control block */
+ memset(p_cb, 0, sizeof(tBTA_HL_CB));
+ p_cb->enable = TRUE;
+ p_cb->p_ctrl_cback = p_data->api_enable.p_cback;
+ evt_data.enable_cfm.status = BTA_HL_STATUS_OK;
+ if (p_data->api_enable.p_cback)
+ p_data->api_enable.p_cback(BTA_HL_CTRL_ENABLE_CFM_EVT, (tBTA_HL_CTRL *) &evt_data);
+
+}
+/*******************************************************************************
+**
+** Function bta_hl_api_disable
+**
+** Description Process the API disable request to disable the HL subsystem
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_disable(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_CTRL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+
+ if (p_cb->enable)
+ {
+ p_cb->disabling = TRUE;
+ bta_hl_check_disable(p_data);
+ }
+ else
+ {
+ status = BTA_HL_STATUS_FAIL;
+ evt_data.disable_cfm.status = status;
+ if (p_cb->p_ctrl_cback) p_cb->p_ctrl_cback(BTA_HL_CTRL_DISABLE_CFM_EVT, (tBTA_HL_CTRL *) &evt_data);
+ }
+
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_disable status =%s", bta_hl_status_code(status));
+ }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_api_register
+**
+** Description Process the API registration request to register an HDP applciation
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_register(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ UINT8 app_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
+
+ if (p_cb->enable)
+ {
+ if (!bta_hl_is_a_duplicate_id(p_data->api_reg.app_id))
+ {
+ if (bta_hl_find_avail_app_idx(&app_idx))
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ p_acb->in_use = TRUE;
+ p_acb->app_id = p_data->api_reg.app_id;
+ p_acb->p_cback = p_data->api_reg.p_cback;
+ p_acb->sec_mask = p_data->api_reg.sec_mask;
+ p_acb->dev_type = p_data->api_reg.dev_type;
+ BCM_STRNCPY_S(p_acb->srv_name, sizeof(p_acb->srv_name), p_data->api_reg.srv_name, BTA_SERVICE_NAME_LEN);
+ BCM_STRNCPY_S(p_acb->srv_desp, sizeof(p_acb->srv_desp), p_data->api_reg.srv_desp, BTA_SERVICE_DESP_LEN);
+ BCM_STRNCPY_S(p_acb->provider_name, sizeof(p_acb->provider_name), p_data->api_reg.provider_name, BTA_PROVIDER_NAME_LEN);
+ bta_hl_cb.p_alloc_psm = L2CA_AllocatePSM;
+ p_acb->ctrl_psm = bta_hl_cb.p_alloc_psm();
+ p_acb->data_psm = bta_hl_cb.p_alloc_psm();
+ p_acb->p_mcap_cback = bta_hl_mcap_ctrl_cback;
+ status = bta_hl_app_registration(app_idx);
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_DUPLICATE_APP_ID;
+ }
+ }
+
+ if (status != BTA_HL_STATUS_OK)
+ {
+ if ((status != BTA_HL_STATUS_DUPLICATE_APP_ID) &&
+ (status != BTA_HL_STATUS_NO_RESOURCE))
+ {
+ memset(p_acb, 0, sizeof(tBTA_HL_APP_CB));
+ }
+ }
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_register status =%s", bta_hl_status_code(status));
+ }
+#endif
+
+ evt_data.reg_cfm.status = status;
+ evt_data.reg_cfm.app_id = p_data->api_reg.app_id;
+ evt_data.reg_cfm.app_handle = p_acb->app_handle;
+ if (p_data->api_reg.p_cback)
+ {
+ p_data->api_reg.p_cback(BTA_HL_REGISTER_CFM_EVT, (tBTA_HL *) &evt_data);
+ }
+
+ if (status == BTA_HL_STATUS_OK)
+ {
+ evt_data.sdp_info_ind.app_handle = p_acb->app_handle;
+ evt_data.sdp_info_ind.ctrl_psm = p_acb->ctrl_psm;
+ evt_data.sdp_info_ind.data_psm = p_acb->data_psm;
+ evt_data.sdp_info_ind.data_x_spec = BTA_HL_SDP_IEEE_11073_20601;
+ evt_data.sdp_info_ind.mcap_sup_procs = BTA_HL_MCAP_SUP_PROC_MASK ;
+
+ if (p_data->api_reg.p_cback)
+ {
+ p_data->api_reg.p_cback(BTA_HL_SDP_INFO_IND_EVT, (tBTA_HL *) &evt_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_api_deregister
+**
+** Description Process the API de-registration request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_deregister(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+
+ UINT8 app_idx;
+ tBTA_HL_APP_CB *p_acb;
+
+ if (bta_hl_find_app_idx_using_handle(p_data->api_dereg.app_handle, &app_idx))
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ p_acb->deregistering= TRUE;
+ bta_hl_check_deregistration(app_idx,p_data);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("Inavlide app_handle=%d", p_data->api_dereg.app_handle);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_api_cch_open
+**
+** Description Process the API CCH open request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_cch_open(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+
+ if (bta_hl_find_app_idx_using_handle(p_data->api_cch_open.app_handle, &app_idx))
+ {
+
+ if (!bta_hl_find_mcl_idx(app_idx, p_data->api_cch_open.bd_addr, &mcl_idx))
+ {
+ if (bta_hl_find_avail_mcl_idx(app_idx, &mcl_idx))
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ p_mcb->in_use = TRUE;
+ p_mcb->req_ctrl_psm = p_data->api_cch_open.ctrl_psm;
+ p_mcb->sec_mask = p_data->api_cch_open.sec_mask;
+ bdcpy(p_mcb->bd_addr, p_data->api_cch_open.bd_addr);
+ p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_OPEN;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ /* Only one MCL per BD_ADDR */
+ status = BTA_HL_STATUS_FAIL;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_APP_HANDLE;
+ }
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_cch_open status =%s", bta_hl_status_code(status));
+ }
+#endif
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_OPEN_EVT, p_data);
+ break;
+ case BTA_HL_STATUS_NO_RESOURCE:
+ case BTA_HL_STATUS_FAIL:
+ bta_hl_build_cch_open_cfm(&evt_data, p_data->api_cch_open.app_handle,
+ 0,
+ p_data->api_cch_open.bd_addr,
+ status);
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ p_acb->p_cback(BTA_HL_CCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+ default:
+ APPL_TRACE_ERROR1("status code=%d", status);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_api_cch_close
+**
+** Description Process the API CCH close request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_cch_close(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+
+ if (bta_hl_find_mcl_idx_using_handle(p_data->api_cch_close.mcl_handle, &app_idx, &mcl_idx))
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+ }
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_cch_close status =%s", bta_hl_status_code(status));
+ }
+#endif
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+ bta_hl_check_cch_close(app_idx, mcl_idx, p_data, TRUE);
+ break;
+
+ case BTA_HL_STATUS_FAIL:
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ bta_hl_build_cch_close_cfm(&evt_data,
+ p_acb->app_handle,
+ p_data->api_cch_close.mcl_handle,
+ status);
+ p_acb->p_cback(BTA_HL_CCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+
+ default:
+ APPL_TRACE_ERROR1("status code=%d", status);
+ break;
+
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_api_dch_open
+**
+** Description Process the API DCH open request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_open(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+ tBTA_HL_MDL_CB *p_dcb;
+ tBTA_HL_MDEP_CFG *p_mdep_cfg;
+ UINT8 mdep_cfg_idx;
+
+ if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_open.mcl_handle, &app_idx, &mcl_idx))
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+ if (p_mcb->cch_state == BTA_HL_CCH_OPEN_ST)
+ {
+ if (bta_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+ if (bta_hl_find_mdep_cfg_idx(app_idx, p_data->api_dch_open.local_mdep_id, &mdep_cfg_idx))
+ {
+ if ( mdep_cfg_idx &&
+ (p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SINK))
+ {
+ p_data->api_dch_open.local_cfg = BTA_HL_DCH_CFG_NO_PREF;
+ }
+
+ if ((status = bta_hl_chk_local_cfg(app_idx,mcl_idx,mdep_cfg_idx,p_data->api_dch_open.local_cfg))
+ == BTA_HL_STATUS_OK)
+ {
+
+ if (p_data->api_dch_open.local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ if (bta_hl_set_ctrl_psm_for_dch(app_idx, mcl_idx, mdl_idx, p_data->api_dch_open.ctrl_psm))
+ {
+ p_mdep_cfg = BTA_HL_GET_MDEP_CFG_PTR(app_idx, mdep_cfg_idx);
+ p_dcb->in_use = TRUE;
+ p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_OPEN;
+ p_dcb->sec_mask = p_data->api_dch_open.sec_mask;
+ p_dcb->local_mdep_id = p_data->api_dch_open.local_mdep_id;
+ p_dcb->peer_mdep_id = p_data->api_dch_open.peer_mdep_id;
+
+ if (p_mdep_cfg->mdep_role == BTA_HL_MDEP_ROLE_SINK)
+ {
+ p_dcb->peer_mdep_role = BTA_HL_MDEP_ROLE_SOURCE;
+ }
+ else
+ {
+ p_dcb->peer_mdep_role = BTA_HL_MDEP_ROLE_SINK;
+ }
+
+ p_dcb->local_mdep_cfg_idx = mdep_cfg_idx;
+ p_dcb->local_cfg = p_data->api_dch_open.local_cfg;
+
+ bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
+ &p_dcb->max_rx_apdu_size,
+ &p_dcb->max_tx_apdu_size);
+ p_dcb->mdl_id = bta_hl_allocate_mdl_id(app_idx,mcl_idx,mdl_idx);
+ p_dcb->mdl_cfg_idx_included = FALSE;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_CTRL_PSM;
+ }
+
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID;
+ }
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_CCH;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_dch_open status =%s", bta_hl_status_code(status));
+ }
+#endif
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+ if (p_mcb->sdp.num_recs)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_OPEN_EVT, p_data);
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_INIT_EVT, p_data);
+ }
+ break;
+ case BTA_HL_STATUS_INVALID_DCH_CFG:
+ case BTA_HL_STATUS_NO_FIRST_RELIABLE:
+ case BTA_HL_STATUS_NO_CCH:
+ case BTA_HL_STATUS_NO_RESOURCE:
+ case BTA_HL_STATUS_FAIL:
+ case BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID:
+ case BTA_HL_STATUS_INVALID_CTRL_PSM:
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ bta_hl_build_dch_open_cfm(&evt_data,
+ p_acb->app_handle,
+ p_data->api_dch_open.mcl_handle,
+ BTA_HL_INVALID_MDL_HANDLE,
+ 0,0,0,0,0, status);
+ p_acb->p_cback(BTA_HL_DCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+ default:
+ APPL_TRACE_ERROR1("Status code=%d", status);
+ break;
+
+ }
+
+}
+/*******************************************************************************
+**
+** Function bta_hl_api_dch_close
+**
+** Description Process the API DCH close request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_close(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+ tBTA_HL_MDL_CB *p_dcb;
+
+
+ if (bta_hl_find_mdl_idx_using_handle(p_data->api_dch_close.mdl_handle, &app_idx, &mcl_idx, &mdl_idx ))
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ if (p_dcb->dch_state != BTA_HL_DCH_OPEN_ST)
+ {
+ status = BTA_HL_STATUS_FAIL;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_MDL_HANDLE;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_dch_close status =%s", bta_hl_status_code(status));
+ }
+#endif
+
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT, p_data);
+ break;
+ case BTA_HL_STATUS_FAIL:
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ bta_hl_build_dch_close_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_data->api_dch_close.mdl_handle,
+ status);
+
+ p_acb->p_cback(BTA_HL_DCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+ default:
+ APPL_TRACE_ERROR1("Status code=%d", status);
+ break;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_api_dch_reconnect
+**
+** Description Process the API DCH reconnect request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_reconnect(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+ tBTA_HL_MDL_CB *p_dcb;
+ UINT8 mdep_cfg_idx;
+ UINT8 mdl_cfg_idx;
+
+ if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_open.mcl_handle, &app_idx, &mcl_idx))
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ if (p_mcb->cch_state == BTA_HL_CCH_OPEN_ST)
+ {
+ if (bta_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ if (bta_hl_validate_reconnect_params(app_idx, mcl_idx, &(p_data->api_dch_reconnect),
+ &mdep_cfg_idx, &mdl_cfg_idx ))
+ {
+ if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx) &&
+ (p_acb->mdl_cfg[mdl_cfg_idx].dch_mode != BTA_HL_DCH_MODE_RELIABLE))
+ {
+ status = BTA_HL_STATUS_NO_FIRST_RELIABLE;
+ }
+ else
+ {
+ if (bta_hl_set_ctrl_psm_for_dch(app_idx, mcl_idx, mdl_idx, p_data->api_dch_open.ctrl_psm))
+ {
+ p_dcb->in_use = TRUE;
+ p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_RECONNECT;
+ p_dcb->sec_mask = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ p_dcb->local_mdep_id = p_acb->mdl_cfg[mdl_cfg_idx].local_mdep_id;
+ p_dcb->local_mdep_cfg_idx = mdep_cfg_idx;
+ p_dcb->local_cfg = BTA_HL_DCH_CFG_UNKNOWN;
+ p_dcb->mdl_id = p_data->api_dch_reconnect.mdl_id;
+ p_dcb->mdl_cfg_idx_included = TRUE;
+ p_dcb->mdl_cfg_idx = mdl_cfg_idx;
+ p_dcb->dch_mode = p_acb->mdl_cfg[mdl_cfg_idx].dch_mode;
+ bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
+ &p_dcb->max_rx_apdu_size,
+ &p_dcb->max_tx_apdu_size);
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_CTRL_PSM;
+ }
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_RECONNECT_CFG;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_CCH;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_dch_reconnect status=%s", bta_hl_status_code(status));
+ }
+#endif
+
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+ if (p_mcb->sdp.num_recs)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_RECONNECT_EVT, p_data);
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_INIT_EVT, p_data);
+ }
+ break;
+ case BTA_HL_STATUS_INVALID_RECONNECT_CFG:
+ case BTA_HL_STATUS_NO_FIRST_RELIABLE:
+ case BTA_HL_STATUS_NO_CCH:
+ case BTA_HL_STATUS_NO_RESOURCE:
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ bta_hl_build_dch_open_cfm(&evt_data,
+ p_acb->app_handle,
+ p_data->api_dch_reconnect.mcl_handle,
+ BTA_HL_INVALID_MDL_HANDLE,
+ 0,p_data->api_dch_reconnect.mdl_id,0,0,0, status);
+ p_acb->p_cback(BTA_HL_DCH_RECONNECT_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+ default:
+ APPL_TRACE_ERROR1("Status code=%d", status);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_api_dch_echo_test
+**
+** Description Process the API Echo test request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_echo_test(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+ tBTA_HL_MDL_CB *p_dcb;
+ tBTA_HL_ECHO_CFG *p_echo_cfg;
+
+
+ if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_echo_test.mcl_handle, &app_idx, &mcl_idx))
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ if (p_mcb->cch_state == BTA_HL_CCH_OPEN_ST)
+ {
+ if (!p_mcb->echo_test )
+ {
+ if (bta_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+ if ((p_data->api_dch_echo_test.local_cfg == BTA_HL_DCH_CFG_RELIABLE) ||
+ (p_data->api_dch_echo_test.local_cfg == BTA_HL_DCH_CFG_STREAMING))
+ {
+ if ((p_dcb->p_echo_tx_pkt = bta_hl_get_buf(p_data->api_dch_echo_test.pkt_size)) != NULL )
+ {
+ if (bta_hl_set_ctrl_psm_for_dch(app_idx, mcl_idx, mdl_idx, p_data->api_dch_open.ctrl_psm))
+ {
+ p_dcb->in_use = TRUE;
+ p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_OPEN;
+ p_dcb->sec_mask = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ p_dcb->local_mdep_cfg_idx = BTA_HL_ECHO_TEST_MDEP_CFG_IDX;
+ p_dcb->local_cfg = p_data->api_dch_echo_test.local_cfg;
+ p_dcb->local_mdep_id = BTA_HL_ECHO_TEST_MDEP_ID;
+ p_dcb->peer_mdep_id = BTA_HL_ECHO_TEST_MDEP_ID;
+ p_dcb->mdl_id = bta_hl_allocate_mdl_id(app_idx,mcl_idx,mdl_idx);
+ p_dcb->mdl_cfg_idx_included = FALSE;
+ p_echo_cfg = BTA_HL_GET_ECHO_CFG_PTR(app_idx);
+ p_dcb->max_rx_apdu_size = p_echo_cfg->max_rx_apdu_size;
+ p_dcb->max_tx_apdu_size = p_echo_cfg->max_tx_apdu_size;
+ p_mcb->echo_test = TRUE;
+ p_mcb->echo_mdl_idx = mdl_idx;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_CTRL_PSM;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_DCH_CFG;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_ECHO_TEST_BUSY;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_CCH;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_MCL;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_dch_echo_test status=%s", bta_hl_status_code(status));
+ }
+#endif
+
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+ if (p_mcb->sdp.num_recs)
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ECHO_TEST_EVT, p_data);
+ }
+ else
+ {
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_INIT_EVT, p_data);
+ }
+ break;
+ case BTA_HL_STATUS_NO_CCH:
+ case BTA_HL_STATUS_ECHO_TEST_BUSY:
+ case BTA_HL_STATUS_NO_RESOURCE:
+ case BTA_HL_STATUS_INVALID_DCH_CFG:
+ bta_hl_build_echo_test_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ status);
+ p_acb->p_cback(BTA_HL_DCH_ECHO_TEST_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+
+ default:
+ APPL_TRACE_ERROR1("Status code=%s", status);
+ break;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_api_sdp_query
+**
+** Description Process the API SDP query request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_sdp_query(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+
+
+ if (bta_hl_find_app_idx_using_handle(p_data->api_sdp_query.app_handle, &app_idx))
+ {
+ if (!bta_hl_find_mcl_idx(app_idx, p_data->api_sdp_query.bd_addr, &mcl_idx))
+ {
+ if (bta_hl_find_avail_mcl_idx(app_idx, &mcl_idx))
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ p_mcb->in_use = TRUE;
+ bdcpy(p_mcb->bd_addr, p_data->api_sdp_query.bd_addr);
+ p_mcb->sdp_oper = BTA_HL_SDP_OP_SDP_QUERY_NEW ;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ if (p_mcb->sdp_oper != BTA_HL_SDP_OP_NONE)
+ {
+ status = BTA_HL_STATUS_SDP_NO_RESOURCE;
+ }
+ else
+ {
+ p_mcb->sdp_oper = BTA_HL_SDP_OP_SDP_QUERY_CURRENT;
+ }
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_APP_HANDLE;
+ }
+
+ if (status == BTA_HL_STATUS_OK)
+ {
+ status = bta_hl_init_sdp( p_mcb->sdp_oper, app_idx, mcl_idx, 0xFF);
+ if ( (status != BTA_HL_STATUS_OK) &&
+ (p_mcb->sdp_oper == BTA_HL_SDP_OP_SDP_QUERY_NEW) )
+ {
+ memset(p_mcb, 0 ,sizeof(tBTA_HL_MCL_CB));
+ }
+ }
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_sdp_query status=%s", bta_hl_status_code(status));
+ }
+#endif
+ switch (status)
+ {
+ case BTA_HL_STATUS_NO_RESOURCE:
+ case BTA_HL_STATUS_FAIL:
+ case BTA_HL_STATUS_SDP_NO_RESOURCE:
+ bta_hl_build_sdp_query_cfm(&evt_data,
+ p_data->api_sdp_query.app_handle,
+ p_data->api_sdp_query.bd_addr,
+ NULL,
+ status);
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ p_acb->p_cback(BTA_HL_SDP_QUERY_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+ case BTA_HL_STATUS_OK:
+ break;
+ default:
+ APPL_TRACE_ERROR1("Status code=%d", status);
+ break;
+ }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_sdp_query_results
+**
+** Description Process the SDP query results
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_sdp_query_results(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx = p_data->cch_sdp.app_idx;
+ UINT8 mcl_idx = p_data->cch_sdp.mcl_idx;
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR( app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR( app_idx, mcl_idx);
+ tBTA_HL_SDP *p_sdp=NULL;
+ tBTA_HL_SDP_OPER sdp_oper;
+ UINT16 event;
+ BOOLEAN release_sdp_buf=FALSE;
+
+ event = p_data->hdr.event;
+ sdp_oper = p_mcb->sdp_oper;
+
+ if ( event == BTA_HL_SDP_QUERY_OK_EVT)
+ {
+ if ((p_sdp = (tBTA_HL_SDP *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_SDP)))) != NULL)
+ {
+ memcpy(p_sdp, &p_mcb->sdp, sizeof(tBTA_HL_SDP));
+ release_sdp_buf = TRUE;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_SDP_NO_RESOURCE;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_SDP_FAIL;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_sdp_query_results status=%s", bta_hl_status_code(status));
+ }
+#endif
+
+ bta_hl_build_sdp_query_cfm(&evt_data,p_acb->app_handle,
+ p_mcb->bd_addr,p_sdp,status);
+ p_acb->p_cback(BTA_HL_SDP_QUERY_CFM_EVT,(tBTA_HL *) &evt_data );
+
+ if (release_sdp_buf)
+ {
+ utl_freebuf((void **) &p_sdp);
+ }
+
+ if (p_data->cch_sdp.release_mcl_cb)
+ {
+ memset(p_mcb, 0 ,sizeof(tBTA_HL_MCL_CB));
+ }
+ else
+ {
+ if (p_mcb->close_pending)
+ {
+ bta_hl_check_cch_close(app_idx,mcl_idx,p_data, TRUE);
+ }
+
+ if (!p_mcb->ctrl_psm)
+ {
+ /* this is a control channel acceptor do not store the sdp records*/
+ memset(&p_mcb->sdp, 0, sizeof(tBTA_HL_SDP));
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_api_delete_mdl
+**
+** Description Process the API DELETE MDL request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_delete_mdl(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+
+ if (bta_hl_find_mcl_idx_using_handle(p_data->api_delete_mdl.mcl_handle, &app_idx, &mcl_idx ))
+ {
+ if (bta_hl_is_mdl_value_valid(p_data->api_delete_mdl.mdl_id))
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ if (bta_hl_is_mdl_exsit_in_mcl(app_idx,
+ p_mcb->bd_addr,
+ p_data->api_delete_mdl.mdl_id))
+ {
+
+
+ p_mcb->delete_mdl.mcl_handle = p_data->api_delete_mdl.mcl_handle;
+ p_mcb->delete_mdl.mdl_id = p_data->api_delete_mdl.mdl_id;
+ p_mcb->delete_mdl.delete_req_pending = TRUE;
+
+ if (MCA_Delete((tMCA_CL) p_mcb->mcl_handle,
+ p_data->api_delete_mdl.mdl_id)!= MCA_SUCCESS)
+ {
+ status = BTA_HL_STATUS_FAIL;
+ memset(&p_mcb->delete_mdl, 0, sizeof(tBTA_HL_DELETE_MDL));
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_NO_MDL_ID_FOUND;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_MDL_ID;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_delete_mdl status=%s", bta_hl_status_code(status));
+ }
+#endif
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+ break;
+ case BTA_HL_STATUS_FAIL:
+ case BTA_HL_STATUS_NO_MDL_ID_FOUND:
+ case BTA_HL_STATUS_INVALID_MDL_ID:
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ bta_hl_build_delete_mdl_cfm(&evt_data,
+ p_acb->app_handle,
+ p_data->api_delete_mdl.mcl_handle,
+ p_data->api_delete_mdl.mdl_id,
+ status);
+
+ p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+ case BTA_HL_STATUS_INVALID_APP_HANDLE:
+ default:
+ APPL_TRACE_ERROR1("status code =%d", status);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_mca_delete_mdl_cfm
+**
+** Description Process the DELETE MDL confirmation event
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_mca_delete_mdl_cfm(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx;
+ tMCA_RSP_EVT *p_delete_cfm = &p_data->mca_evt.mca_data.delete_cfm;
+ tBTA_HL_MCL_CB *p_mcb;
+ BOOLEAN send_cfm_evt = TRUE;
+ tBTA_HL_APP_CB *p_acb;
+
+ if (bta_hl_find_mcl_idx_using_handle(p_data->mca_evt.mcl_handle, &app_idx, &mcl_idx))
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ if ( p_mcb->delete_mdl.delete_req_pending)
+ {
+ if (p_delete_cfm->rsp_code == MCA_RSP_SUCCESS )
+ {
+
+ if (!bta_hl_delete_mdl_cfg(app_idx,
+ p_mcb->bd_addr ,
+ p_delete_cfm->mdl_id))
+ {
+ status = BTA_HL_STATUS_FAIL;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_FAIL;
+ }
+
+ memset(&p_mcb->delete_mdl, 0, sizeof(tBTA_HL_DELETE_MDL));
+ }
+ else
+ {
+ send_cfm_evt = FALSE;
+ }
+ }
+ else
+ {
+ send_cfm_evt = FALSE;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_delete_mdl status=%s", bta_hl_status_code(status));
+ }
+#endif
+
+ if (send_cfm_evt)
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ bta_hl_build_delete_mdl_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ p_delete_cfm->mdl_id,
+ status);
+
+ p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_mca_delete_mdl_ind
+**
+** Description Process the DELETE MDL indication event
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_mca_delete_mdl_ind(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+ tBTA_HL evt_data;
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ tMCA_EVT_HDR *p_delete_ind = &p_data->mca_evt.mca_data.delete_ind;
+ tBTA_HL_MCL_CB *p_mcb;
+ tBTA_HL_MDL_CB *p_dcb;
+ BOOLEAN send_ind_evt = TRUE;
+ tBTA_HL_APP_CB *p_acb;
+
+ if (bta_hl_find_mcl_idx_using_handle(p_data->mca_evt.mcl_handle, &app_idx, &mcl_idx) )
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+ if (bta_hl_find_mdl_idx(app_idx, mcl_idx, p_delete_ind->mdl_id, &mdl_idx ))
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_DELETE;
+ }
+ if (bta_hl_delete_mdl_cfg(app_idx,
+ p_mcb->bd_addr ,
+ p_delete_ind->mdl_id))
+ {
+ send_ind_evt = TRUE;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!send_ind_evt)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_mca_delete_mdl_ind is_send_ind_evt =%d", send_ind_evt);
+ }
+#endif
+
+ if (send_ind_evt)
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ evt_data.delete_mdl_ind.mcl_handle = p_mcb->mcl_handle;
+ evt_data.delete_mdl_ind.app_handle = p_acb->app_handle;
+ evt_data.delete_mdl_ind.mdl_id = p_delete_ind->mdl_id;
+ p_acb->p_cback(BTA_HL_DELETE_MDL_IND_EVT,(tBTA_HL *) &evt_data );
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_api_dch_abort
+**
+** Description Process the API DCH abort request
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_abort(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+ tBTA_HL_MDL_CB *p_dcb;
+ tBTA_HL evt_data;
+
+
+ if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_abort.mcl_handle, &app_idx, &mcl_idx ))
+ {
+
+ if (!bta_hl_find_dch_setup_mdl_idx(app_idx, mcl_idx, &mdl_idx ))
+ {
+ status = BTA_HL_STATUS_NO_MDL_ID_FOUND;
+ }
+ else
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ if (p_dcb->abort_oper)
+ {
+ /* abort already in progress*/
+ status = BTA_HL_STATUS_FAIL;
+ }
+ else
+ {
+ p_dcb->abort_oper = BTA_HL_ABORT_LOCAL_MASK;
+ }
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+ }
+
+
+#if BTA_HL_DEBUG == TRUE
+ if (status != BTA_HL_STATUS_OK)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_api_dch_abort status=%s", bta_hl_status_code(status));
+ }
+#endif
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT, p_data);
+ break;
+ case BTA_HL_STATUS_NO_MDL_ID_FOUND:
+ case BTA_HL_STATUS_FAIL:
+
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ bta_hl_build_abort_cfm(&evt_data,
+ p_acb->app_handle,
+ p_mcb->mcl_handle,
+ BTA_HL_STATUS_FAIL);
+ p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT,(tBTA_HL *) &evt_data );
+ break;
+ case BTA_HL_STATUS_INVALID_BD_ADDR:
+ case BTA_HL_STATUS_INVALID_APP_HANDLE:
+ default:
+ APPL_TRACE_ERROR1("Status code=%d", status);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_hdl_event
+**
+** Description HL main event handling function.
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_hl_hdl_event(BT_HDR *p_msg)
+{
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ BOOLEAN success = TRUE;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("BTA HL Event Handler: Event [%s]",
+ bta_hl_evt_code(p_msg->event));
+#endif
+
+ switch (p_msg->event)
+ {
+ case BTA_HL_API_ENABLE_EVT:
+ bta_hl_api_enable(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_DISABLE_EVT:
+ bta_hl_api_disable(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_REGISTER_EVT:
+ bta_hl_api_register(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_DEREGISTER_EVT:
+ bta_hl_api_deregister(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_CCH_OPEN_EVT:
+ bta_hl_api_cch_open(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_CCH_CLOSE_EVT:
+ bta_hl_api_cch_close(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_DCH_OPEN_EVT:
+ bta_hl_api_dch_open(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_DCH_CLOSE_EVT:
+ bta_hl_api_dch_close(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_DELETE_MDL_EVT:
+ bta_hl_api_delete_mdl(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_DCH_RECONNECT_EVT:
+ bta_hl_api_dch_reconnect(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+
+ case BTA_HL_API_DCH_ECHO_TEST_EVT:
+ bta_hl_api_dch_echo_test(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+
+ case BTA_HL_API_SDP_QUERY_EVT:
+ bta_hl_api_sdp_query(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+
+ case BTA_HL_MCA_DELETE_CFM_EVT:
+ bta_hl_mca_delete_mdl_cfm(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+
+ case BTA_HL_MCA_DELETE_IND_EVT:
+ bta_hl_mca_delete_mdl_ind(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+
+ case BTA_HL_SDP_QUERY_OK_EVT:
+ case BTA_HL_SDP_QUERY_FAIL_EVT:
+ bta_hl_sdp_query_results(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+ case BTA_HL_API_DCH_ABORT_EVT:
+ bta_hl_api_dch_abort(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+ break;
+
+
+ default:
+ if (p_msg->event < BTA_HL_DCH_EVT_MIN)
+ {
+ if (bta_hl_find_cch_cb_indexes((tBTA_HL_DATA *) p_msg, &app_idx, &mcl_idx))
+ {
+ bta_hl_cch_sm_execute( app_idx,
+ mcl_idx,
+ p_msg->event, (tBTA_HL_DATA *) p_msg);
+ }
+ else
+ {
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_ERROR1("unable to find control block indexes for CCH: [event=%s]",
+ bta_hl_evt_code(p_msg->event));
+#else
+ APPL_TRACE_ERROR1("unable to find control block indexes for CCH: [event=%d]", p_msg->event);
+#endif
+ success = FALSE;
+ }
+ }
+ else
+ {
+ if (bta_hl_find_dch_cb_indexes((tBTA_HL_DATA *) p_msg, &app_idx, &mcl_idx, &mdl_idx))
+ {
+ bta_hl_dch_sm_execute( app_idx,
+ mcl_idx,
+ mdl_idx,
+ p_msg->event, (tBTA_HL_DATA *) p_msg);
+ }
+ else
+ {
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_ERROR1("unable to find control block indexes for DCH : [event=%s]",
+ bta_hl_evt_code(p_msg->event));
+#else
+ APPL_TRACE_ERROR1("unable to find control block indexes for DCH: [event=%d]", p_msg->event);
+#endif
+ success = FALSE;
+ }
+ }
+
+ break;
+ }
+
+ return(success);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+
+/*******************************************************************************
+**
+** Function bta_hl_cch_state_code
+**
+** Description Map CCH state code to the corresponding state string
+**
+** Returns string pointer for the associated state name
+**
+*******************************************************************************/
+static char *bta_hl_cch_state_code(tBTA_HL_CCH_STATE state_code)
+{
+ switch (state_code)
+ {
+ case BTA_HL_CCH_IDLE_ST:
+ return "BTA_HL_CCH_IDLE_ST";
+ case BTA_HL_CCH_OPENING_ST:
+ return "BTA_HL_CCH_OPENING_ST";
+ case BTA_HL_CCH_OPEN_ST:
+ return "BTA_HL_CCH_OPEN_ST";
+ case BTA_HL_CCH_CLOSING_ST:
+ return "BTA_HL_CCH_CLOSING_ST";
+ default:
+ return "Unknown CCH state code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_dch_state_code
+**
+** Description Map DCH state code to the corresponding state string
+**
+** Returns string pointer for the associated state name
+**
+*******************************************************************************/
+static char *bta_hl_dch_state_code(tBTA_HL_DCH_STATE state_code)
+{
+ switch (state_code)
+ {
+ case BTA_HL_DCH_IDLE_ST:
+ return "BTA_HL_DCH_IDLE_ST";
+ case BTA_HL_DCH_OPENING_ST:
+ return "BTA_HL_DCH_OPENING_ST";
+ case BTA_HL_DCH_OPEN_ST:
+ return "BTA_HL_DCH_OPEN_ST";
+ case BTA_HL_DCH_CLOSING_ST:
+ return "BTA_HL_DCH_CLOSING_ST";
+ default:
+ return "Unknown DCH state code";
+ }
+}
+#endif /* Debug Functions */
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_sdp.c b/bta/hl/bta_hl_sdp.c
new file mode 100644
index 0000000..15620e8
--- /dev/null
+++ b/bta/hl/bta_hl_sdp.c
@@ -0,0 +1,436 @@
+/******************************************************************************
+ *
+ * Copyright (C) 1998-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+#include "sdp_api.h"
+#include "bta_hl_int.h"
+
+
+/*******************************************************************************
+**
+** Function bta_hl_fill_sup_feature_list
+**
+** Description Fill the supported features from teh SDP record
+**
+** Returns TRUE if found, FALSE if not
+** If found, the passed protocol list element is filled in.
+**
+*******************************************************************************/
+BOOLEAN bta_hl_fill_sup_feature_list( const tSDP_DISC_ATTR *p_attr,
+ tBTA_HL_SUP_FEATURE_LIST_ELEM *p_list)
+{
+ tSDP_DISC_ATTR *p_sattr;
+ UINT8 seq_len, item_cnt;
+ UINT8 list_cnt=0;
+ BOOLEAN status=TRUE;
+
+ for (p_attr = p_attr->attr_value.v.p_sub_attr; p_attr; p_attr = p_attr->p_next_attr)
+ {
+ /* mdep sequence */
+ if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE)
+ {
+ return(FALSE);
+ }
+ seq_len =SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ item_cnt=0;
+
+ for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr && (item_cnt < 4) ; p_sattr = p_sattr->p_next_attr)
+ {
+ /* for each mdep list */
+
+ p_list->list_elem[list_cnt].p_mdep_desp = NULL;
+ switch (item_cnt)
+ {
+ case 0:
+ p_list->list_elem[list_cnt].mdep_id = p_sattr->attr_value.v.u8;
+ break;
+ case 1:
+ p_list->list_elem[list_cnt].data_type = p_sattr->attr_value.v.u16;
+ break;
+ case 2:
+ p_list->list_elem[list_cnt].mdep_role = (tBTA_HL_MDEP_ROLE) p_sattr->attr_value.v.u8;
+ break;
+ case 3:
+ p_list->list_elem[list_cnt].p_mdep_desp = (char *) p_sattr->attr_value.v.array;
+ break;
+ }
+
+ item_cnt++;
+ }
+ list_cnt++;
+ }
+ p_list->num_elems = list_cnt;
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_compose_supported_feature_list
+**
+** Description This function is called to compose a data sequence from
+** the supported feature element list struct pointer
+**
+** Returns the length of the data sequence
+**
+*******************************************************************************/
+int bta_hl_compose_supported_feature_list( UINT8 *p, UINT16 num_elem,
+ const tBTA_HL_SUP_FEATURE_ELEM *p_elem_list)
+{
+ UINT16 xx, str_len, seq_len;
+ UINT8 *p_head = p;
+
+ for (xx = 0; xx < num_elem; xx++, p_elem_list++)
+ {
+ UINT8_TO_BE_STREAM (p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
+ seq_len=7;
+ str_len=0;
+ if (p_elem_list->p_mdep_desp)
+ {
+ str_len = strlen(p_elem_list->p_mdep_desp)+1;
+ seq_len += str_len+2; /* todo add a # symbol for 2 */
+ }
+
+ *p++ = (UINT8) seq_len;
+
+ UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
+ UINT8_TO_BE_STREAM (p, p_elem_list->mdep_id);
+ UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
+ UINT16_TO_BE_STREAM (p, p_elem_list->data_type);
+ UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
+ UINT8_TO_BE_STREAM (p, p_elem_list->mdep_role);
+
+ if (str_len)
+ {
+ UINT8_TO_BE_STREAM (p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
+ UINT8_TO_BE_STREAM (p, str_len);
+ ARRAY_TO_BE_STREAM(p, p_elem_list->p_mdep_desp, str_len);
+ }
+ }
+
+ return(p - p_head);
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_add_sup_feature_list
+**
+** Description This function is called to add a protocol descriptor list to
+** a record. This would be through the SDP database maintenance API.
+** If the protocol list already exists in the record, it is replaced
+** with the new list.
+**
+** Returns TRUE if added OK, else FALSE
+**
+*******************************************************************************/
+BOOLEAN bta_hl_add_sup_feature_list (UINT32 handle, UINT16 num_elem,
+ const tBTA_HL_SUP_FEATURE_ELEM *p_elem_list)
+{
+ UINT8 *p_buf;
+ int offset;
+ BOOLEAN result = FALSE;
+
+ if ((p_buf = (UINT8 *)GKI_getbuf(BTA_HL_SUP_FEATURE_SDP_BUF_SIZE)) != NULL)
+ {
+ offset = bta_hl_compose_supported_feature_list(p_buf, num_elem, p_elem_list);
+ result = SDP_AddAttribute (handle, ATTR_ID_HDP_SUP_FEAT_LIST,
+ DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, p_buf);
+ GKI_freebuf(p_buf);
+ }
+ return result;
+}
+/*****************************************************************************
+**
+** Function: bta_hl_sdp_register
+**
+** Purpose: Register an HDP application with SDP
+**
+** Parameters: p_cb - Pointer to MA instance control block
+** p_service_name - MA server name
+** inst_id - MAS instance ID
+** msg_type - Supported message type(s)
+**
+**
+** Returns: void
+**
+*****************************************************************************/
+tBTA_HL_STATUS bta_hl_sdp_register (UINT8 app_idx)
+{
+ UINT16 svc_class_id_list[BTA_HL_NUM_SVC_ELEMS];
+ tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HL_NUM_PROTO_ELEMS];
+ tSDP_PROTO_LIST_ELEM add_proto_list;
+ tBTA_HL_SUP_FEATURE_LIST_ELEM sup_feature_list;
+ UINT16 browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
+ UINT8 i,j, cnt,mdep_id, mdep_role;
+ UINT8 data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601;
+ UINT8 mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK;
+ UINT16 profile_uuid = UUID_SERVCLASS_HDP_PROFILE;
+ UINT16 version = BTA_HL_VERSION_01_00;
+ UINT8 num_services=1;
+ tBTA_HL_APP_CB *p_cb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ BOOLEAN result = TRUE;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_sdp_register app_idx=%d",app_idx);
+#endif
+
+ if ((p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE) &&
+ (!p_cb->sup_feature.advertize_source_sdp))
+ {
+ return BTA_HL_STATUS_OK;
+ }
+
+ if ((p_cb->sdp_handle = SDP_CreateRecord()) == 0)
+ {
+ return BTA_HL_STATUS_SDP_NO_RESOURCE;
+ }
+
+ num_services=1;
+ svc_class_id_list[0]= UUID_SERVCLASS_HDP_SOURCE;
+ if (p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SINK)
+ {
+ svc_class_id_list[0]= UUID_SERVCLASS_HDP_SINK;
+ }
+ else
+ {
+ if (p_cb->sup_feature.app_role_mask != BTA_HL_MDEP_ROLE_MASK_SOURCE)
+ {
+ /* dual role */
+ num_services=2;
+ svc_class_id_list[1]= UUID_SERVCLASS_HDP_SINK;
+ }
+ }
+ result &= SDP_AddServiceClassIdList(p_cb->sdp_handle, num_services, svc_class_id_list);
+
+ if (result)
+ {
+ /* add the protocol element sequence */
+ proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+ proto_elem_list[0].num_params = 1;
+ proto_elem_list[0].params[0] = p_cb->ctrl_psm;
+ proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_MCAP_CTRL;
+ proto_elem_list[1].num_params = 1;
+ proto_elem_list[1].params[0] = version;
+ result &= SDP_AddProtocolList(p_cb->sdp_handle, BTA_HL_NUM_PROTO_ELEMS, proto_elem_list);
+
+ result &= SDP_AddProfileDescriptorList(p_cb->sdp_handle, profile_uuid, version);
+ }
+
+ if (result)
+ {
+ add_proto_list.num_elems = BTA_HL_NUM_ADD_PROTO_ELEMS;
+ add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+ add_proto_list.list_elem[0].num_params = 1;
+ add_proto_list.list_elem[0].params[0] = p_cb->data_psm;
+ add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA;
+ add_proto_list.list_elem[1].num_params = 0;
+ result &= SDP_AddAdditionProtoLists(p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS,
+ (tSDP_PROTO_LIST_ELEM *)&add_proto_list);
+ }
+
+ if (result)
+ {
+ if (p_cb->srv_name[0] )
+ {
+ result &= SDP_AddAttribute(p_cb->sdp_handle,
+ (UINT16)ATTR_ID_SERVICE_NAME,
+ (UINT8)TEXT_STR_DESC_TYPE,
+ (UINT32)(strlen(p_cb->srv_name) + 1),
+ (UINT8 *)p_cb->srv_name);
+ } /* end of setting optional service name */
+ }
+
+ if (result)
+ {
+ if (p_cb->srv_desp[0] )
+ {
+ result &= SDP_AddAttribute(p_cb->sdp_handle,
+ (UINT16)ATTR_ID_SERVICE_DESCRIPTION,
+ (UINT8)TEXT_STR_DESC_TYPE,
+ (UINT32)(strlen(p_cb->srv_desp) + 1),
+ (UINT8 *)p_cb->srv_desp);
+
+ } /* end of setting optional service description */
+
+ }
+
+ if (result)
+ {
+ if (p_cb->provider_name[0] )
+ {
+ result &= SDP_AddAttribute(p_cb->sdp_handle,
+ (UINT16)ATTR_ID_PROVIDER_NAME,
+ (UINT8)TEXT_STR_DESC_TYPE,
+ (UINT32)(strlen(p_cb->provider_name) + 1),
+ (UINT8 *)p_cb->provider_name);
+ } /* end of setting optional provider name */
+ }
+
+ /* add supported feture list */
+
+ if (result)
+ {
+ cnt=0;
+ for (i=1; i<= p_cb->sup_feature.num_of_mdeps; i++)
+ {
+ mdep_id = (UINT8)p_cb->sup_feature.mdep[i].mdep_id;
+ mdep_role = (UINT8)p_cb->sup_feature.mdep[i].mdep_cfg.mdep_role;
+
+ for (j=0; j<p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types; j++)
+ {
+ sup_feature_list.list_elem[cnt].mdep_id = mdep_id;
+ sup_feature_list.list_elem[cnt].mdep_role = mdep_role;
+ sup_feature_list.list_elem[cnt].data_type = p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].data_type;
+ if (p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp[0] != '\0')
+ {
+ sup_feature_list.list_elem[cnt].p_mdep_desp = p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp;
+ }
+ else
+ {
+ sup_feature_list.list_elem[cnt].p_mdep_desp = NULL;
+ }
+
+ cnt++;
+ if (cnt>BTA_HL_NUM_SUP_FEATURE_ELEMS)
+ {
+ result = FALSE;
+ break;
+ }
+ }
+ }
+ sup_feature_list.num_elems = cnt;
+ result &= bta_hl_add_sup_feature_list (p_cb->sdp_handle,
+ sup_feature_list.num_elems,
+ sup_feature_list.list_elem);
+ }
+ if (result)
+ {
+ result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_DATA_EXCH_SPEC, UINT_DESC_TYPE,
+ (UINT32)1, (UINT8*)&data_exchange_spec);
+ }
+
+ if (result)
+ {
+
+ result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_MCAP_SUP_PROC, UINT_DESC_TYPE,
+ (UINT32)1, (UINT8*)&mcap_sup_proc);
+ }
+
+ if (result)
+ {
+ result &= SDP_AddUuidSequence(p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
+ }
+
+ if (result)
+ {
+ for(i=0; i < num_services; i++)
+ {
+ bta_sys_add_uuid(svc_class_id_list[i]);
+ APPL_TRACE_DEBUG2("dbg bta_sys_add_uuid i=%d uuid=0x%x", i, svc_class_id_list[i]); //todo
+ }
+ }
+ else
+ {
+ if (p_cb->sdp_handle)
+ {
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ p_cb->sdp_handle = 0;
+ }
+ status = BTA_HL_STATUS_SDP_FAIL;
+ }
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_sdp_register status=%s", bta_hl_status_code(status));
+#endif
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_sink_or_src_srv_class_in_db
+**
+** Description This function queries an SDP database for either a HDP Sink or
+** Source service class ID.
+** If the p_start_rec pointer is NULL, it looks from the beginning
+** of the database, else it continues from the next record after
+** p_start_rec.
+**
+** Returns Pointer to record containing service class, or NULL
+**
+*******************************************************************************/
+tSDP_DISC_REC *bta_hl_find_sink_or_src_srv_class_in_db (const tSDP_DISCOVERY_DB *p_db,
+ const tSDP_DISC_REC *p_start_rec)
+{
+#if SDP_CLIENT_ENABLED == TRUE
+ tSDP_DISC_REC *p_rec;
+ tSDP_DISC_ATTR *p_attr, *p_sattr;
+
+ /* Must have a valid database */
+ if (p_db == NULL)
+ return(NULL);
+
+
+ if (!p_start_rec)
+ {
+
+ p_rec = p_db->p_first_rec;
+ }
+ else
+ {
+ p_rec = p_start_rec->p_next_rec;
+ }
+
+ while (p_rec)
+ {
+ p_attr = p_rec->p_first_attr;
+ while (p_attr)
+ {
+ if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST)
+ && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
+ {
+ for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
+ {
+ if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
+ && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)
+ && ( (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SINK) ||
+ (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SOURCE)) )
+ {
+ return(p_rec);
+ }
+ }
+ break;
+ }
+
+ p_attr = p_attr->p_next_attr;
+ }
+
+ p_rec = p_rec->p_next_rec;
+ }
+#endif
+ /* If here, no matching UUID found */
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_find_sink_or_src_srv_class_in_db failed");
+#endif
+
+ return(NULL);
+}
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_utils.c b/bta/hl/bta_hl_utils.c
new file mode 100644
index 0000000..7f94a9c
--- /dev/null
+++ b/bta/hl/bta_hl_utils.c
@@ -0,0 +1,3337 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file implements utility functions for the HeaLth device profile
+ * (HL).
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+
+#include "gki.h"
+#include "utl.h"
+#include "bd.h"
+#include "bta_fs_api.h"
+#include "bta_hl_int.h"
+#include "bta_hl_co.h"
+#include "mca_defs.h"
+#include "mca_api.h"
+
+
+/*******************************************************************************
+**
+** Function bta_hl_set_ctrl_psm_for_dch
+**
+** Description This function set the control PSM for the DCH setup
+**
+** Returns BOOLEAN - TRUE - control PSM setting is successful
+*******************************************************************************/
+BOOLEAN bta_hl_set_ctrl_psm_for_dch(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx, UINT16 ctrl_psm)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ BOOLEAN success = TRUE, update_ctrl_psm = FALSE;
+
+ if (p_mcb->sdp.num_recs)
+ {
+ if (p_mcb->ctrl_psm != ctrl_psm)
+ {
+ /* can not use a different ctrl PSM than the current one*/
+ success = FALSE;
+ }
+ }
+ else
+ {
+ /* No SDP info control i.e. channel was opened by the peer */
+ update_ctrl_psm = TRUE;
+ }
+
+ if (success && update_ctrl_psm)
+ {
+ p_mcb->ctrl_psm = ctrl_psm;
+ }
+
+
+#if BTA_HL_DEBUG == TRUE
+ if (!success)
+ {
+ APPL_TRACE_DEBUG4("bta_hl_set_ctrl_psm_for_dch num_recs=%d success=%d update_ctrl_psm=%d ctrl_psm=0x%x ",
+ p_mcb->sdp.num_recs, success, update_ctrl_psm, ctrl_psm );
+ }
+#endif
+
+ return success;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_find_sdp_idx_using_ctrl_psm
+**
+** Description
+**
+** Returns UINT8 pool_id
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_sdp_idx_using_ctrl_psm(tBTA_HL_SDP *p_sdp,
+ UINT16 ctrl_psm,
+ UINT8 *p_sdp_idx)
+{
+ BOOLEAN found=FALSE;
+ tBTA_HL_SDP_REC *p_rec;
+ UINT8 i;
+
+ if (ctrl_psm != 0)
+ {
+ for (i=0; i<p_sdp->num_recs; i++)
+ {
+ p_rec = &p_sdp->sdp_rec[i];
+ if (p_rec->ctrl_psm == ctrl_psm)
+ {
+ *p_sdp_idx = i;
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ else
+ {
+ *p_sdp_idx = 0;
+ found = TRUE;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG3("bta_hl_find_sdp_idx_using_ctrl_psm found=%d sdp_idx=%d ctrl_psm=0x%x ",
+ found, *p_sdp_idx, ctrl_psm );
+ }
+#endif
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_set_user_tx_pool_id
+**
+** Description This function sets the user tx pool id
+**
+** Returns UINT8 pool_id
+**
+*******************************************************************************/
+
+UINT8 bta_hl_set_user_tx_pool_id(UINT16 max_tx_size)
+{
+ UINT8 pool_id;
+
+ if (max_tx_size > GKI_get_pool_bufsize (OBX_FCR_TX_POOL_ID))
+ {
+ pool_id = BTA_HL_LRG_DATA_POOL_ID;
+ }
+ else
+ {
+ pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG3("bta_hl_set_user_rx_pool_id pool_id=%d max_tx_size=%d default_ertm_pool_size=%d",
+ pool_id, max_tx_size, GKI_get_pool_bufsize (OBX_FCR_TX_POOL_ID));
+#endif
+
+ return pool_id;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_set_user_rx_pool_id
+**
+** Description This function sets the user trx pool id
+**
+** Returns UINT8 pool_id
+**
+*******************************************************************************/
+
+UINT8 bta_hl_set_user_rx_pool_id(UINT16 mtu)
+{
+ UINT8 pool_id;
+
+ if (mtu > GKI_get_pool_bufsize (OBX_FCR_RX_POOL_ID))
+ {
+ pool_id = BTA_HL_LRG_DATA_POOL_ID;
+ }
+ else
+ {
+ pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG3("bta_hl_set_user_rx_pool_id pool_id=%d mtu=%d default_ertm_pool_size=%d",
+ pool_id, mtu, GKI_get_pool_bufsize (OBX_FCR_RX_POOL_ID));
+#endif
+
+ return pool_id;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_set_tx_win_size
+**
+** Description This function sets the tx window size
+**
+** Returns UINT8 tx_win_size
+**
+*******************************************************************************/
+UINT8 bta_hl_set_tx_win_size(UINT16 mtu, UINT16 mps)
+{
+ UINT8 tx_win_size;
+
+ if (mtu <= mps)
+ {
+ tx_win_size =1;
+ }
+ else
+ {
+ if (mps > 0)
+ {
+ tx_win_size = (mtu/mps)+1;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("The MPS is zero");
+ tx_win_size = 10;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG3("bta_hl_set_tx_win_size win_size=%d mtu=%d mps=%d",
+ tx_win_size, mtu, mps);
+#endif
+ return tx_win_size;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_set_mps
+**
+** Description This function sets the MPS
+**
+** Returns UINT16 MPS
+**
+*******************************************************************************/
+UINT16 bta_hl_set_mps(UINT16 mtu)
+{
+ UINT16 mps;
+ if (mtu > BTA_HL_L2C_MPS)
+ {
+ mps = BTA_HL_L2C_MPS;
+ }
+ else
+ {
+ mps = mtu;
+ }
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG2("bta_hl_set_mps mps=%d mtu=%d",
+ mps, mtu);
+#endif
+ return mps;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_clean_mdl_cb
+**
+** Description This function clean up the specified MDL control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_clean_mdl_cb(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx)
+{
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG3("bta_hl_clean_mdl_cb app_idx=%d mcl_idx=%d mdl_idx=%d",
+ app_idx, mcl_idx, mdl_idx);
+#endif
+ utl_freebuf((void **) &p_dcb->p_tx_pkt);
+ utl_freebuf((void **) &p_dcb->p_rx_pkt);
+ utl_freebuf((void **) &p_dcb->p_echo_tx_pkt);
+ utl_freebuf((void **) &p_dcb->p_echo_rx_pkt);
+
+ memset((void *)p_dcb, 0 , sizeof(tBTA_HL_MDL_CB));
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_get_buf
+**
+** Description This function allocate a buffer based on the specified data size
+**
+** Returns BT_HDR *.
+**
+*******************************************************************************/
+BT_HDR * bta_hl_get_buf(UINT16 data_size)
+{
+ BT_HDR *p_new;
+ UINT16 size = data_size + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
+
+ if (size < GKI_MAX_BUF_SIZE)
+ {
+ p_new = (BT_HDR *)GKI_getbuf(size);
+ }
+ else
+ {
+ p_new = (BT_HDR *) GKI_getpoolbuf(BTA_HL_LRG_DATA_POOL_ID);
+ }
+
+ if (p_new)
+ {
+ p_new->len = data_size;
+ p_new->offset = L2CAP_MIN_OFFSET;
+ }
+
+ return p_new;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_service_in_db
+**
+** Description This function check the specified service class(es) can be find in
+** the received SDP database
+**
+** Returns BOOLEAN TRUE - found
+** FALSE - not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_service_in_db( UINT8 app_idx, UINT8 mcl_idx,
+ UINT16 service_uuid,
+ tSDP_DISC_REC **pp_rec )
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ BOOLEAN found = TRUE;
+
+ switch (service_uuid)
+ {
+ case UUID_SERVCLASS_HDP_SINK:
+ case UUID_SERVCLASS_HDP_SOURCE:
+ if ((*pp_rec = SDP_FindServiceInDb(p_mcb->p_db, service_uuid,
+ *pp_rec)) == NULL)
+ {
+ found = FALSE;
+ }
+ break;
+ default:
+ if (((*pp_rec = bta_hl_find_sink_or_src_srv_class_in_db(p_mcb->p_db,
+ *pp_rec)) == NULL))
+ {
+ found = FALSE;
+ }
+ break;
+ }
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_get_service_uuids
+**
+**
+** Description This function finds the service class(es) for both CCH and DCH oeprations
+**
+** Returns UINT16 - service_id
+** if service_uuid = 0xFFFF then it means service uuid
+** can be either Sink or Source
+**
+*******************************************************************************/
+UINT16 bta_hl_get_service_uuids(UINT8 sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdl_idx )
+{
+ tBTA_HL_MDL_CB *p_dcb;
+ UINT16 service_uuid = 0xFFFF; /* both Sink and Source */
+
+ switch (sdp_oper)
+ {
+
+ case BTA_HL_SDP_OP_DCH_OPEN_INIT:
+ case BTA_HL_SDP_OP_DCH_RECONNECT_INIT:
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ if (p_dcb->peer_mdep_role == BTA_HL_MDEP_ROLE_SINK)
+ {
+ service_uuid = UUID_SERVCLASS_HDP_SINK;
+ }
+ else
+ {
+ service_uuid = UUID_SERVCLASS_HDP_SOURCE;
+ }
+ }
+ break;
+ case BTA_HL_SDP_OP_CCH_INIT:
+ default:
+ /* use default that is both Sink and Source */
+ break;
+ }
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_get_service_uuids service_uuid=0x%x",service_uuid );
+#endif
+ return service_uuid;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_echo_cfg_rsp
+**
+**
+** Description This function finds the configuration response for the echo test
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_echo_cfg_rsp(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdep_idx, UINT8 cfg,
+ UINT8 *p_cfg_rsp)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MDEP *p_mdep= &p_acb->sup_feature.mdep[mdep_idx];
+ BOOLEAN status =TRUE;
+
+ if (p_mdep->mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ if ((cfg == BTA_HL_DCH_CFG_RELIABLE) || (cfg == BTA_HL_DCH_CFG_STREAMING))
+ {
+ *p_cfg_rsp = cfg;
+ }
+ else if (cfg == BTA_HL_DCH_CFG_NO_PREF )
+ {
+ *p_cfg_rsp = BTA_HL_DEFAULT_ECHO_TEST_SRC_DCH_CFG;
+ }
+ else
+ {
+ status = FALSE;
+ APPL_TRACE_ERROR0("Inavlid echo cfg value");
+ }
+ return status;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!status)
+ {
+ APPL_TRACE_DEBUG4("bta_hl_find_echo_cfg_rsp status=failed app_idx=%d mcl_idx=%d mdep_idx=%d cfg=%d",
+ app_idx, mcl_idx, mdep_idx, cfg);
+ }
+#endif
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_validate_dch_cfg
+**
+** Description This function validate the DCH configuration
+**
+** Returns BOOLEAN - TRUE cfg is valid
+** FALSE not valid
+**
+*******************************************************************************/
+BOOLEAN bta_hl_validate_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ UINT8 cfg)
+{
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ BOOLEAN is_valid =FALSE;
+
+
+ if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx) &&
+ (cfg != BTA_HL_DCH_CFG_RELIABLE))
+ {
+ APPL_TRACE_ERROR0("the first DCH should be a reliable channel");
+ return is_valid;
+ }
+
+ switch (p_dcb->local_cfg)
+ {
+ case BTA_HL_DCH_CFG_NO_PREF:
+
+ if ((cfg == BTA_HL_DCH_CFG_RELIABLE) || (cfg == BTA_HL_DCH_CFG_STREAMING))
+ {
+ is_valid = TRUE;
+ }
+ break;
+ case BTA_HL_DCH_CFG_RELIABLE:
+ case BTA_HL_DCH_CFG_STREAMING:
+ if (p_dcb->local_cfg == cfg )
+ {
+ is_valid = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!is_valid)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_validate_dch_open_cfg is_valid=%d, cfg=%d", is_valid, cfg );
+ }
+#endif
+ return is_valid;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_cch_cb_indexes
+**
+** Description This function finds the indexes needed for the CCH state machine
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_cch_cb_indexes(tBTA_HL_DATA *p_msg,
+ UINT8 *p_app_idx,
+ UINT8 *p_mcl_idx)
+{
+ BOOLEAN found = FALSE;
+ tBTA_HL_MCL_CB *p_mcb;
+ UINT8 app_idx, mcl_idx;
+
+ switch (p_msg->hdr.event)
+ {
+ case BTA_HL_CCH_SDP_OK_EVT:
+ case BTA_HL_CCH_SDP_FAIL_EVT:
+ app_idx = p_msg->cch_sdp.app_idx;
+ mcl_idx = p_msg->cch_sdp.mcl_idx;
+ found = TRUE;
+ break;
+
+ case BTA_HL_MCA_CONNECT_IND_EVT:
+
+ if (bta_hl_find_app_idx_using_handle(p_msg->mca_evt.app_handle, &app_idx))
+ {
+ if (bta_hl_find_mcl_idx(app_idx, p_msg->mca_evt.mca_data.connect_ind.bd_addr, &mcl_idx))
+ {
+ /* local initiated */
+ found = TRUE;
+ }
+ else if (!bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx)&&
+ bta_hl_find_avail_mcl_idx(app_idx, &mcl_idx))
+ {
+ /* remote initiated */
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ p_mcb->in_use = TRUE;
+ p_mcb->cch_oper = BTA_HL_CCH_OP_REMOTE_OPEN;
+ found = TRUE;
+ }
+ }
+ break;
+
+ case BTA_HL_MCA_DISCONNECT_IND_EVT:
+
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx))
+ {
+ found = TRUE;
+ }
+ else if (bta_hl_find_app_idx_using_handle(p_msg->mca_evt.app_handle, &app_idx) &&
+ bta_hl_find_mcl_idx(app_idx, p_msg->mca_evt.mca_data.disconnect_ind.bd_addr, &mcl_idx))
+ {
+ found = TRUE;
+ }
+
+ if (found)
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ if (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE)
+ {
+ p_mcb->cch_oper = BTA_HL_CCH_OP_REMOTE_CLOSE;
+ }
+ }
+ break;
+
+ case BTA_HL_MCA_RSP_TOUT_IND_EVT:
+
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx))
+ {
+ found = TRUE;
+ }
+
+ if (found)
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ if (p_mcb->cch_oper != BTA_HL_CCH_OP_REMOTE_CLOSE)
+ {
+ p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ if (found)
+ {
+ *p_app_idx = app_idx;
+ *p_mcl_idx = mcl_idx;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG4("bta_hl_find_cch_cb_indexes event=%s found=%d app_idx=%d mcl_idx=%d",
+ bta_hl_evt_code(p_msg->hdr.event), found, app_idx, mcl_idx);
+ }
+#endif
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_dch_cb_indexes
+**
+** Description This function finds the indexes needed for the DCH state machine
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_dch_cb_indexes(tBTA_HL_DATA *p_msg,
+ UINT8 *p_app_idx,
+ UINT8 *p_mcl_idx,
+ UINT8 *p_mdl_idx)
+{
+ BOOLEAN found = FALSE;
+ tBTA_HL_MCL_CB *p_mcb;
+ UINT8 app_idx, mcl_idx, mdl_idx;
+
+ switch (p_msg->hdr.event)
+ {
+ case BTA_HL_MCA_CREATE_CFM_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+ bta_hl_find_mdl_idx( app_idx, mcl_idx, p_msg->mca_evt.mca_data.create_cfm.mdl_id, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+
+ case BTA_HL_MCA_CREATE_IND_EVT:
+ case BTA_HL_MCA_RECONNECT_IND_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+ bta_hl_find_avail_mdl_idx( app_idx, mcl_idx, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+
+ case BTA_HL_MCA_OPEN_CFM_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+ bta_hl_find_mdl_idx( app_idx, mcl_idx, p_msg->mca_evt.mca_data.open_cfm.mdl_id, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+
+ case BTA_HL_MCA_OPEN_IND_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+ bta_hl_find_mdl_idx( app_idx, mcl_idx, p_msg->mca_evt.mca_data.open_ind.mdl_id, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+
+ case BTA_HL_MCA_CLOSE_CFM_EVT:
+
+ if (bta_hl_find_mdl_idx_using_handle((tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.close_cfm.mdl,
+ &app_idx, &mcl_idx, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+ case BTA_HL_MCA_CLOSE_IND_EVT:
+
+ if (bta_hl_find_mdl_idx_using_handle((tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.close_ind.mdl,
+ &app_idx, &mcl_idx, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+ case BTA_HL_API_SEND_DATA_EVT:
+
+ if (bta_hl_find_mdl_idx_using_handle(p_msg->api_send_data.mdl_handle,
+ &app_idx, &mcl_idx, &mdl_idx ))
+ {
+ found = TRUE;
+ }
+
+ break;
+
+ case BTA_HL_MCA_CONG_CHG_EVT:
+
+ if (bta_hl_find_mdl_idx_using_handle((tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.cong_chg.mdl,
+ &app_idx, &mcl_idx, &mdl_idx ))
+ {
+ found = TRUE;
+ }
+
+ break;
+
+ case BTA_HL_MCA_RCV_DATA_EVT:
+ app_idx = p_msg->mca_rcv_data_evt.app_idx;
+ mcl_idx = p_msg->mca_rcv_data_evt.mcl_idx;
+ mdl_idx = p_msg->mca_rcv_data_evt.mdl_idx;
+ found = TRUE;
+ break;
+ case BTA_HL_DCH_RECONNECT_EVT:
+ case BTA_HL_DCH_OPEN_EVT:
+ case BTA_HL_DCH_ECHO_TEST_EVT:
+ case BTA_HL_DCH_SDP_FAIL_EVT:
+ app_idx = p_msg->dch_sdp.app_idx;
+ mcl_idx = p_msg->dch_sdp.mcl_idx;
+ mdl_idx = p_msg->dch_sdp.mdl_idx;
+ found = TRUE;
+ break;
+ case BTA_HL_MCA_RECONNECT_CFM_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+ bta_hl_find_mdl_idx( app_idx, mcl_idx, p_msg->mca_evt.mca_data.reconnect_cfm.mdl_id, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+
+
+ case BTA_HL_API_DCH_CREATE_RSP_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->api_dch_create_rsp.mcl_handle, &app_idx, &mcl_idx)&&
+ bta_hl_find_mdl_idx( app_idx, mcl_idx,p_msg->api_dch_create_rsp.mdl_id, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+ case BTA_HL_MCA_ABORT_IND_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+ bta_hl_find_mdl_idx( app_idx, mcl_idx,p_msg->mca_evt.mca_data.abort_ind.mdl_id, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+ case BTA_HL_MCA_ABORT_CFM_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+ bta_hl_find_mdl_idx( app_idx, mcl_idx, p_msg->mca_evt.mca_data.abort_cfm.mdl_id, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+ case BTA_HL_CI_GET_TX_DATA_EVT:
+ case BTA_HL_CI_PUT_RX_DATA_EVT:
+ if (bta_hl_find_mdl_idx_using_handle(p_msg->ci_get_put_data.mdl_handle, &app_idx, &mcl_idx, &mdl_idx))
+ {
+ found = TRUE;
+ }
+ break;
+ case BTA_HL_CI_GET_ECHO_DATA_EVT:
+ case BTA_HL_CI_PUT_ECHO_DATA_EVT:
+ if (bta_hl_find_mcl_idx_using_handle(p_msg->ci_get_put_echo_data.mcl_handle, &app_idx, &mcl_idx))
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ mdl_idx = p_mcb->echo_mdl_idx;
+ found = TRUE;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+
+ if (found)
+ {
+ *p_app_idx = app_idx;
+ *p_mcl_idx = mcl_idx;
+ *p_mdl_idx = mdl_idx;
+ }
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG5("bta_hl_find_dch_cb_indexes event=%s found=%d app_idx=%d mcl_idx=%d mdl_idx=%d",
+ bta_hl_evt_code(p_msg->hdr.event), found, *p_app_idx, *p_mcl_idx, *p_mdl_idx );
+ }
+#endif
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_allocate_mdl_id
+**
+** Description This function allocates a MDL ID
+**
+** Returns UINT16 - MDL ID
+**
+*******************************************************************************/
+UINT16 bta_hl_allocate_mdl_id(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx )
+{
+ UINT16 mdl_id=0;
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ BOOLEAN duplicate_id;
+ UINT8 i, mdl_cfg_idx;
+
+ do
+ {
+ duplicate_id = FALSE;
+ mdl_id = ((mdl_id+1) & 0xFEFF);
+ /* check mdl_ids that are used for the current conenctions */
+ for (i=0; i< BTA_HL_NUM_MDLS_PER_MCL; i++)
+ {
+ if (p_mcb->mdl[i].in_use &&
+ (i != mdl_idx) &&
+ (p_mcb->mdl[i].mdl_id == mdl_id) )
+ {
+ duplicate_id = TRUE;
+ break;
+ }
+ }
+
+ if (duplicate_id)
+ {
+ /* start from the beginning to get another MDL value*/
+ continue;
+ }
+ else
+ {
+ /* check mdl_ids that are stored in the persistent memory */
+ if (bta_hl_find_mdl_cfg_idx(app_idx,mcl_idx, mdl_id, &mdl_cfg_idx))
+ {
+ duplicate_id = TRUE;
+ }
+ else
+ {
+ /* found a new MDL value */
+ break;
+ }
+ }
+
+ }while (TRUE);
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_allocate_mdl OK mdl_id=%d", mdl_id);
+#endif
+ return mdl_id;
+}
+/*******************************************************************************
+**
+** Function bta_hl_find_mdl_idx
+**
+** Description This function finds the MDL index based on mdl_id
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mdl_idx(UINT8 app_idx, UINT8 mcl_idx, UINT16 mdl_id,
+ UINT8 *p_mdl_idx)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++)
+ {
+ if (p_mcb->mdl[i].in_use &&
+ (mdl_id !=0) &&
+ (p_mcb->mdl[i].mdl_id== mdl_id))
+ {
+ found = TRUE;
+ *p_mdl_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG3("bta_hl_find_mdl_idx found=%d mdl_id=%d mdl_idx=%d ",
+ found, mdl_id, i);
+ }
+#endif
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_an_active_mdl_idx
+**
+** Description This function finds an active MDL
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_an_active_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 *p_mdl_idx)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++)
+ {
+ if (p_mcb->mdl[i].in_use &&
+ (p_mcb->mdl[i].dch_state == BTA_HL_DCH_OPEN_ST))
+ {
+ found = TRUE;
+ *p_mdl_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (found)
+ {
+ APPL_TRACE_DEBUG4("bta_hl_find_an_opened_mdl_idx found=%d app_idx=%d mcl_idx=%d mdl_idx=%d",
+ found, app_idx, mcl_idx, i);
+ }
+#endif
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_dch_setup_mdl_idx
+**
+** Description This function finds a MDL which in the DCH setup state
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_dch_setup_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 *p_mdl_idx)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++)
+ {
+ if (p_mcb->mdl[i].in_use &&
+ (p_mcb->mdl[i].dch_state == BTA_HL_DCH_OPENING_ST))
+ {
+ found = TRUE;
+ *p_mdl_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (found)
+ {
+ APPL_TRACE_DEBUG4("bta_hl_find_dch_setup_mdl_idx found=%d app_idx=%d mcl_idx=%d mdl_idx=%d",
+ found, app_idx, mcl_idx, i);
+ }
+#endif
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_an_in_use_mcl_idx
+**
+** Description This function finds an in-use MCL control block index
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_an_in_use_mcl_idx(UINT8 app_idx,
+ UINT8 *p_mcl_idx)
+{
+ tBTA_HL_MCL_CB *p_mcb;
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, i);
+ if (p_mcb->in_use &&
+ (p_mcb->cch_state != BTA_HL_CCH_IDLE_ST))
+ {
+ found = TRUE;
+ *p_mcl_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (found)
+ {
+ APPL_TRACE_DEBUG3("bta_hl_find_an_in_use_mcl_idx found=%d app_idx=%d mcl_idx=%d ",
+ found, app_idx, i);
+ }
+#endif
+
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_find_an_in_use_app_idx
+**
+** Description This function finds an in-use application control block index
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_an_in_use_app_idx(UINT8 *p_app_idx)
+{
+ tBTA_HL_APP_CB *p_acb ;
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(i);
+ if (p_acb->in_use)
+ {
+ found = TRUE;
+ *p_app_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (found)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_find_an_in_use_app_idx found=%d app_idx=%d ",
+ found, i);
+ }
+#endif
+
+ return found;
+}
+/*******************************************************************************
+**
+** Function bta_hl_find_app_idx
+**
+** Description This function finds the application control block index based on
+** the application ID
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_app_idx(UINT8 app_id, UINT8 *p_app_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+ {
+ if (bta_hl_cb.acb[i].in_use &&
+ (bta_hl_cb.acb[i].app_id == app_id))
+ {
+ found = TRUE;
+ *p_app_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG3("bta_hl_find_app_idx found=%d app_id=%d idx=%d ",
+ found, app_id, i);
+#endif
+
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_find_app_idx_using_handle
+**
+** Description This function finds the application control block index based on
+** the application handle
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_app_idx_using_handle(tBTA_HL_APP_HANDLE app_handle,
+ UINT8 *p_app_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+ {
+ if (bta_hl_cb.acb[i].in_use &&
+ (bta_hl_cb.acb[i].app_handle == app_handle))
+ {
+ found = TRUE;
+ *p_app_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG3("bta_hl_find_app_idx_using_mca_handle status=%d handle=%d app_idx=%d ",
+ found, app_handle , i);
+ }
+#endif
+
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_find_mcl_idx_using_handle
+**
+** Description This function finds the MCL control block index based on
+** the MCL handle
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mcl_idx_using_handle( tBTA_HL_MCL_HANDLE mcl_handle,
+ UINT8 *p_app_idx, UINT8 *p_mcl_idx)
+{
+ tBTA_HL_APP_CB *p_acb;
+ BOOLEAN found=FALSE;
+ UINT8 i,j;
+
+ for (i=0; i<BTA_HL_NUM_APPS; i++)
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(i);
+ if (p_acb->in_use)
+ {
+ for (j=0; j < BTA_HL_NUM_MCLS ; j++)
+ {
+ if ( p_acb->mcb[j].mcl_handle == mcl_handle )
+ {
+ found = TRUE;
+ *p_app_idx = i;
+ *p_mcl_idx = j;
+ break;
+ }
+ }
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG3("bta_hl_find_mcl_idx_using_handle found=%d app_idx=%d mcl_idx=%d",
+ found, i, j);
+ }
+#endif
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_mcl_idx
+**
+** Description This function finds the MCL control block index based on
+** the peer BD address
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mcl_idx(UINT8 app_idx, BD_ADDR p_bd_addr, UINT8 *p_mcl_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+ tBTA_HL_MCL_CB *p_mcb;
+
+ for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, i);
+
+ if (bta_hl_cb.acb[app_idx].mcb[i].in_use &&
+ (!memcmp (bta_hl_cb.acb[app_idx].mcb[i].bd_addr, p_bd_addr, BD_ADDR_LEN)))
+ {
+ found = TRUE;
+ *p_mcl_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_find_mcl_idx found=%d idx=%d",
+ found, i);
+ }
+#endif
+ return found;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_find_mdl_idx_using_handle
+**
+** Description This function finds the MDL control block index based on
+** the MDL handle
+**
+** Returns BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mdl_idx_using_handle(tBTA_HL_MDL_HANDLE mdl_handle,
+ UINT8 *p_app_idx,UINT8 *p_mcl_idx,
+ UINT8 *p_mdl_idx)
+{
+ tBTA_HL_APP_CB *p_acb;
+ tBTA_HL_MCL_CB *p_mcb;
+ tBTA_HL_MDL_CB *p_dcb;
+ BOOLEAN found=FALSE;
+ UINT8 i,j,k;
+
+ for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(i);
+ if (p_acb->in_use)
+ {
+ for (j=0; j< BTA_HL_NUM_MCLS; j++)
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(i,j);
+ if (p_mcb->in_use)
+ {
+ for (k=0; k< BTA_HL_NUM_MDLS_PER_MCL; k++)
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(i,j,k);
+ if (p_dcb->in_use)
+ {
+ if (p_dcb->mdl_handle == mdl_handle)
+ {
+ found = TRUE;
+ *p_app_idx = i;
+ *p_mcl_idx =j;
+ *p_mdl_idx = k;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_find_mdl_idx_using_handle found=%d mdl_handle=%d ",
+ found, mdl_handle);
+ }
+#endif
+ return found;
+}
+/*******************************************************************************
+**
+** Function bta_hl_is_the_first_reliable_existed
+**
+** Description This function checks whether the first reliable DCH channel
+** has been setup on the MCL or not
+**
+** Returns BOOLEAN - TRUE exist
+** FALSE does not exist
+**
+*******************************************************************************/
+BOOLEAN bta_hl_is_the_first_reliable_existed(UINT8 app_idx, UINT8 mcl_idx )
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ BOOLEAN is_existed =FALSE;
+ UINT8 i ;
+
+ for (i=0; i< BTA_HL_NUM_MDLS_PER_MCL; i++)
+ {
+ if (p_mcb->mdl[i].in_use && p_mcb->mdl[i].is_the_first_reliable)
+ {
+ is_existed = TRUE;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_is_the_first_reliable_existed is_existed=%d ",is_existed );
+#endif
+ return is_existed;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_non_active_mdl_cfg
+**
+** Description This function finds a valid MDL configiration index and this
+** MDL ID is not active
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_non_active_mdl_cfg(UINT8 app_idx, UINT8 start_mdl_cfg_idx,
+ UINT8 *p_mdl_cfg_idx)
+{
+
+ tBTA_HL_MCL_CB *p_mcb;
+ tBTA_HL_MDL_CB *p_dcb;
+ tBTA_HL_MDL_CFG *p_mdl;
+ BOOLEAN mdl_in_use;
+ BOOLEAN found = FALSE;
+ UINT8 i,j,k;
+
+ for (i = start_mdl_cfg_idx; i< BTA_HL_NUM_MDL_CFGS; i++)
+ {
+ mdl_in_use = FALSE;
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+ for (j=0; j< BTA_HL_NUM_MCLS; j++)
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, j);
+ if (p_mcb->in_use &&
+ !memcmp(p_mdl->peer_bd_addr,p_mcb->bd_addr,BD_ADDR_LEN))
+ {
+
+ for (k=0; k<BTA_HL_NUM_MDLS_PER_MCL; k++)
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, j, k);
+
+ if (p_dcb->in_use && p_mdl->mdl_id == p_dcb->mdl_id)
+ {
+ mdl_in_use = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (mdl_in_use)
+ {
+ break;
+ }
+ }
+
+ if (!mdl_in_use)
+ {
+ *p_mdl_cfg_idx = i;
+ found = TRUE;
+ break;
+ }
+ }
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_mdl_cfg_idx
+**
+** Description This function finds an available MDL configiration index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_avail_mdl_cfg_idx(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 *p_mdl_cfg_idx)
+{
+ tBTA_HL_MDL_CFG *p_mdl, *p_mdl1, *p_mdl2;
+ UINT8 i;
+ BOOLEAN found=FALSE;
+ UINT8 first_mdl_cfg_idx, second_mdl_cfg_idx, older_mdl_cfg_idx;
+ BOOLEAN done;
+
+
+ for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
+ {
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+ if (!p_mdl->active )
+ {
+ /* found an unused space to store mdl cfg*/
+ found=TRUE;
+ *p_mdl_cfg_idx =i;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ /* all available mdl cfg spaces are in use so we need to find the mdl cfg which is
+ not currently in use and has the the oldest time stamp to remove*/
+
+ found = TRUE;
+ if (bta_hl_find_non_active_mdl_cfg(app_idx,0, &first_mdl_cfg_idx))
+ {
+ if (bta_hl_find_non_active_mdl_cfg(app_idx,(UINT8) (first_mdl_cfg_idx+1), &second_mdl_cfg_idx))
+ {
+ done = FALSE;
+ while (!done)
+ {
+ p_mdl1 = BTA_HL_GET_MDL_CFG_PTR(app_idx, first_mdl_cfg_idx);
+ p_mdl2 = BTA_HL_GET_MDL_CFG_PTR(app_idx, second_mdl_cfg_idx);
+
+ if (p_mdl1->time < p_mdl2->time)
+ {
+ older_mdl_cfg_idx = first_mdl_cfg_idx;
+ }
+ else
+ {
+ older_mdl_cfg_idx = second_mdl_cfg_idx;
+ }
+
+ if (bta_hl_find_non_active_mdl_cfg(app_idx,(UINT8) (second_mdl_cfg_idx+1), &second_mdl_cfg_idx))
+ {
+ first_mdl_cfg_idx = older_mdl_cfg_idx;
+ }
+ else
+ {
+ done = TRUE;
+ }
+ }
+
+ *p_mdl_cfg_idx = older_mdl_cfg_idx;
+
+ }
+ else
+ {
+ *p_mdl_cfg_idx = first_mdl_cfg_idx;
+ }
+
+ }
+ else
+ {
+ found = FALSE;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_find_avail_mdl_cfg_idx found=%d mdl_cfg_idx=%d ",found, *p_mdl_cfg_idx );
+ }
+#endif
+
+ return found;
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_mdl_cfg_idx
+**
+** Description This function finds the MDL configuration index based on
+** the MDL ID
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mdl_cfg_idx(UINT8 app_idx, UINT8 mcl_idx,
+ tBTA_HL_MDL_ID mdl_id, UINT8 *p_mdl_cfg_idx)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CFG *p_mdl;
+ UINT8 i ;
+ BOOLEAN found=FALSE;
+ for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
+ {
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+ if (p_mdl->active &&
+ (!memcmp (p_mcb->bd_addr, p_mdl->peer_bd_addr, BD_ADDR_LEN))&&
+ (p_mdl->mdl_id == mdl_id))
+ {
+ found=TRUE;
+ *p_mdl_cfg_idx =i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_find_mdl_cfg_idx found=%d mdl_cfg_idx=%d ",found, i );
+ }
+#endif
+
+ return found;
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_get_cur_time
+**
+** Description This function get the cuurent time value
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_get_cur_time(UINT8 app_idx, UINT8 *p_cur_time)
+{
+ tBTA_HL_MDL_CFG *p_mdl;
+ UINT8 i, j, time_latest, time;
+ BOOLEAN found=FALSE, result=TRUE;
+
+ for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
+ {
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+ if (p_mdl->active)
+ {
+ found=TRUE;
+ time_latest = p_mdl->time;
+ for (j=(i+1); j< BTA_HL_NUM_MDL_CFGS; j++ )
+ {
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, j);
+ if (p_mdl->active)
+ {
+ time = p_mdl->time;
+ if (time > time_latest)
+ {
+ time_latest = time;
+ }
+ }
+ }
+ break;
+ }
+ }
+
+
+ if (found)
+ {
+ if (time_latest < BTA_HL_MAX_TIME)
+ {
+ *p_cur_time = time_latest+1;
+ }
+ else
+ {
+ /* need to wrap around */
+ result = FALSE;
+ }
+ }
+ else
+ {
+ *p_cur_time = BTA_HL_MIN_TIME;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!result)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_get_cur_time result=%s cur_time=%d",
+ (result?"OK":"FAIL"), *p_cur_time);
+ }
+#endif
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_sort_cfg_time_idx
+**
+** Description This function sort the mdl configuration idx stored in array a
+** based on decending time value
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+void bta_hl_sort_cfg_time_idx(UINT8 app_idx, UINT8 *a, UINT8 n)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ UINT8 temp_time, temp_idx;
+ INT16 i, j;
+ for (i = 1; i < n; ++i)
+ {
+ temp_idx = a[i];
+ temp_time = p_acb->mdl_cfg[temp_idx].time;
+ j = i - 1;
+ while ((j >= 0) && (temp_time < p_acb->mdl_cfg[a[j]].time))
+ {
+ a[j + 1] = a[j];
+ --j;
+ }
+ a[j + 1] = temp_idx;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_compact_mdl_cfg_time
+**
+** Description This function finds the MDL configuration index based on
+** the MDL ID
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+void bta_hl_compact_mdl_cfg_time(UINT8 app_idx)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MDL_CFG *p_mdl;
+ UINT8 i, time_min, cnt=0;
+ UINT8 s_arr[BTA_HL_NUM_MDL_CFGS];
+
+
+ for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
+ {
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+ if (p_mdl->active )
+ {
+ s_arr[cnt]= i;
+ cnt++;
+ }
+ }
+
+
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_compact_mdl_cfg_time cnt=%d ",cnt );
+#endif
+
+
+ if (cnt)
+ {
+ bta_hl_sort_cfg_time_idx(app_idx, s_arr, cnt);
+ time_min = BTA_HL_MIN_TIME;
+ for (i=0;i<cnt; i++)
+ {
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, s_arr[i]);
+ p_mdl->time = time_min + i;
+ bta_hl_co_save_mdl(p_acb->app_id, s_arr[i], p_mdl);
+ }
+ }
+
+
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_is_mdl_exsit_in_mcl
+**
+** Description This function checks whether the MDL ID
+** has already existed in teh MCL or not
+**
+** Returns BOOLEAN - TRUE exist
+** FALSE does not exist
+**
+*******************************************************************************/
+BOOLEAN bta_hl_is_mdl_exsit_in_mcl(UINT8 app_idx, BD_ADDR bd_addr,
+ tBTA_HL_MDL_ID mdl_id)
+{
+ tBTA_HL_MDL_CFG *p_mdl;
+ BOOLEAN found = FALSE;
+ UINT8 i;
+
+ for (i = 0; i< BTA_HL_NUM_MDL_CFGS; i++)
+ {
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+ if (p_mdl->active &&
+ !memcmp(p_mdl->peer_bd_addr, bd_addr,BD_ADDR_LEN))
+ {
+ if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS)
+ {
+ if (p_mdl->mdl_id == mdl_id)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_delete_mdl_cfg
+**
+** Description This function delete the specified MDL ID
+**
+** Returns BOOLEAN - TRUE Success
+** FALSE Failed
+**
+*******************************************************************************/
+BOOLEAN bta_hl_delete_mdl_cfg(UINT8 app_idx, BD_ADDR bd_addr,
+ tBTA_HL_MDL_ID mdl_id)
+{
+ tBTA_HL_MDL_CFG *p_mdl;
+ BOOLEAN success = FALSE;
+ UINT8 i;
+ tBTA_HL_APP_CB *p_acb= BTA_HL_GET_APP_CB_PTR(app_idx);
+ UINT8 app_id = p_acb->app_id;
+
+ for (i = 0; i< BTA_HL_NUM_MDL_CFGS; i++)
+ {
+ p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+ if (p_mdl->active &&
+ !memcmp(p_mdl->peer_bd_addr, bd_addr,BD_ADDR_LEN))
+ {
+ if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS)
+ {
+ if (p_mdl->mdl_id == mdl_id)
+ {
+ bta_hl_co_delete_mdl(app_id, i);
+ memset(p_mdl, 0, sizeof(tBTA_HL_MDL_CFG));
+ success = TRUE;
+ break;
+ }
+ }
+ else
+ {
+ bta_hl_co_delete_mdl(app_id, i);
+ memset(p_mdl, 0, sizeof(tBTA_HL_MDL_CFG));
+ success = TRUE;
+ }
+ }
+ }
+
+ return success;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_is_mdl_value_valid
+**
+**
+** Description This function checks the specified MDL ID is in valid range or not
+**
+** Returns BOOLEAN - TRUE Success
+** FALSE Failed
+**
+** note: mdl_id range 0x0000 reserved,
+** 0x0001-oxFEFF dynamic range,
+** 0xFF00-0xFFFE reserved,
+** 0xFFFF indicates all MDLs (for delete operation only)
+**
+*******************************************************************************/
+BOOLEAN bta_hl_is_mdl_value_valid(tBTA_HL_MDL_ID mdl_id)
+{
+ BOOLEAN status = TRUE;
+
+ if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS)
+ {
+ if (mdl_id != 0)
+ {
+ if (mdl_id > BTA_HL_MAX_MDL_VAL )
+ {
+ status = FALSE;
+ }
+ }
+ else
+ {
+ status = FALSE;
+ }
+ }
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_mdep_cfg_idx
+**
+** Description This function finds the MDEP configuration index based
+** on the local MDEP ID
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mdep_cfg_idx(UINT8 app_idx, tBTA_HL_MDEP_ID local_mdep_id,
+ UINT8 *p_mdep_cfg_idx)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_SUP_FEATURE *p_sup_feature= &p_acb->sup_feature;
+ BOOLEAN found =FALSE;
+ UINT8 i;
+
+ for (i=0; i< p_sup_feature->num_of_mdeps; i++)
+ {
+ if ( p_sup_feature->mdep[i].mdep_id == local_mdep_id)
+ {
+ found = TRUE;
+ *p_mdep_cfg_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG3("bta_hl_find_mdep_cfg_idx found=%d mdep_idx=%d local_mdep_id=%d ",
+ found,i, local_mdep_id );
+ }
+#endif
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_find_rxtx_apdu_size
+**
+** Description This function finds the maximum APDU rx and tx sizes based on
+** the MDEP configuration data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_find_rxtx_apdu_size(UINT8 app_idx, UINT8 mdep_cfg_idx,
+ UINT16 *p_rx_apu_size,
+ UINT16 *p_tx_apu_size)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MDEP_CFG *p_mdep_cfg;
+ UINT8 i;
+ UINT16 max_rx_apdu_size=0, max_tx_apdu_size=0;
+
+ p_mdep_cfg = &p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg;
+
+
+ for (i=0; i< p_mdep_cfg->num_of_mdep_data_types ; i++)
+ {
+
+ if (max_rx_apdu_size < p_mdep_cfg->data_cfg[i].max_rx_apdu_size)
+ {
+ max_rx_apdu_size = p_mdep_cfg->data_cfg[i].max_rx_apdu_size;
+ }
+
+ if (max_tx_apdu_size < p_mdep_cfg->data_cfg[i].max_tx_apdu_size)
+ {
+ max_tx_apdu_size = p_mdep_cfg->data_cfg[i].max_tx_apdu_size;
+ }
+ }
+
+
+ *p_rx_apu_size = max_rx_apdu_size;
+ *p_tx_apu_size = max_tx_apdu_size;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG2("bta_hl_find_rxtx_apdu_size max_rx_apdu_size=%d max_tx_apdu_size=%d ",
+ max_rx_apdu_size, max_tx_apdu_size );
+#endif
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_validate_peer_cfg
+**
+** Description This function validates the peer DCH configuration
+**
+** Returns BOOLEAN - TRUE validation is successful
+** FALSE validation failed
+**
+*******************************************************************************/
+BOOLEAN bta_hl_validate_peer_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+ tBTA_HL_MDEP_ID peer_mdep_id,
+ tBTA_HL_MDEP_ROLE peer_mdep_role,
+ UINT8 sdp_idx)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ tBTA_HL_SDP_REC *p_rec;
+ BOOLEAN peer_found =FALSE;
+ UINT8 i;
+
+ APPL_TRACE_DEBUG1("bta_hl_validate_peer_cfg sdp_idx=%d", sdp_idx);
+
+
+ if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ return TRUE;
+ }
+
+ p_rec = &p_mcb->sdp.sdp_rec[sdp_idx];
+ for (i=0; i< p_rec->num_mdeps; i++)
+ {
+ if ( (p_rec->mdep_cfg[i].mdep_id == peer_mdep_id) &&
+ (p_rec->mdep_cfg[i].mdep_role == peer_mdep_role))
+ {
+ peer_found = TRUE;
+
+ break;
+ }
+ }
+
+
+#if BTA_HL_DEBUG == TRUE
+ if (!peer_found)
+ {
+ APPL_TRACE_DEBUG1("bta_hl_validate_peer_cfg failed num_mdeps=%d",p_rec->num_mdeps);
+ }
+#endif
+ return peer_found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_chk_local_cfg
+**
+** Description This function check whether the local DCH configuration is OK or not
+**
+** Returns tBTA_HL_STATUS - OK - local DCH configuration is OK
+** NO_FIRST_RELIABLE - the streaming DCH configuration
+** is not OK and it needs to use
+** reliable DCH configuration
+**
+*******************************************************************************/
+tBTA_HL_STATUS bta_hl_chk_local_cfg(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 mdep_cfg_idx,
+ tBTA_HL_DCH_CFG local_cfg)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+
+ if ( mdep_cfg_idx &&
+ (p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SOURCE) &&
+ (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx)) &&
+ (local_cfg != BTA_HL_DCH_CFG_RELIABLE))
+ {
+ status = BTA_HL_STATUS_NO_FIRST_RELIABLE;
+ APPL_TRACE_ERROR0("BTA_HL_STATUS_INVALID_DCH_CFG");
+ }
+
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_validate_reconnect_params
+**
+** Description This function validates the reconnect parameters
+**
+** Returns BOOLEAN - TRUE validation is successful
+** FALSE validation failed
+*******************************************************************************/
+BOOLEAN bta_hl_validate_reconnect_params(UINT8 app_idx, UINT8 mcl_idx,
+ tBTA_HL_API_DCH_RECONNECT *p_reconnect,
+ UINT8 *p_mdep_cfg_idx, UINT8 *p_mdl_cfg_idx)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_SUP_FEATURE *p_sup_feature = &p_acb->sup_feature;
+ UINT8 num_mdeps;
+ UINT8 mdl_cfg_idx;
+ BOOLEAN local_mdep_id_found =FALSE;
+ BOOLEAN mdl_cfg_found =FALSE;
+ BOOLEAN status=FALSE;
+ UINT8 i, in_use_mdl_idx;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_validate_reconnect_params mdl_id=%d", p_reconnect->mdl_id);
+#endif
+ if (bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_reconnect->mdl_id, &mdl_cfg_idx))
+ {
+ mdl_cfg_found = TRUE;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!mdl_cfg_found)
+ {
+ APPL_TRACE_DEBUG0("mdl_cfg_found not found");
+ }
+#endif
+
+
+ if (mdl_cfg_found)
+ {
+ num_mdeps = p_sup_feature->num_of_mdeps;
+ for (i=0; i< num_mdeps ; i++)
+ {
+ if ( p_sup_feature->mdep[i].mdep_id == p_acb->mdl_cfg[mdl_cfg_idx].local_mdep_id)
+ {
+ local_mdep_id_found = TRUE;
+ *p_mdep_cfg_idx =i;
+ *p_mdl_cfg_idx = mdl_cfg_idx;
+ break;
+ }
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!local_mdep_id_found)
+ {
+ APPL_TRACE_DEBUG0("local_mdep_id not found");
+ }
+#endif
+
+
+ if (local_mdep_id_found)
+ {
+ if (!bta_hl_find_mdl_idx(app_idx,mcl_idx, p_reconnect->mdl_id, &in_use_mdl_idx))
+ {
+ status= TRUE;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("mdl_id=%d is curreltly in use",p_reconnect->mdl_id);
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!status)
+ {
+ APPL_TRACE_DEBUG3("Reconnect validation failed local_mdep_id found=%d mdl_cfg_idx found=%d in_use_mdl_idx=%d ",
+ local_mdep_id_found, mdl_cfg_found, in_use_mdl_idx);
+ }
+#endif
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_find_avail_mcl_idx
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_avail_mcl_idx(UINT8 app_idx, UINT8 *p_mcl_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
+ {
+ if (!bta_hl_cb.acb[app_idx].mcb[i].in_use)
+ {
+ found = TRUE;
+ *p_mcl_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_find_avail_mcl_idx found=%d idx=%d",
+ found, i);
+ }
+#endif
+ return found;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_find_avail_mdl_idx
+**
+** Description This function finds an available MDL control block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_avail_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+ UINT8 *p_mdl_idx)
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++)
+ {
+ if (!p_mcb->mdl[i].in_use)
+ {
+ memset((void *)&p_mcb->mdl[i],0, sizeof(tBTA_HL_MDL_CB));
+ found = TRUE;
+ *p_mdl_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_find_avail_mdl_idx found=%d idx=%d",
+ found, i);
+ }
+#endif
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_is_a_duplicate_id
+**
+** Description This function finds the application has been used or not
+**
+** Returns BOOLEAN - TRUE the app_id is a duplicate ID
+** FALSE not a duplicate ID
+*******************************************************************************/
+BOOLEAN bta_hl_is_a_duplicate_id(UINT8 app_id)
+{
+ BOOLEAN is_duplicate=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+ {
+ if (bta_hl_cb.acb[i].in_use &&
+ (bta_hl_cb.acb[i].app_id == app_id))
+ {
+ is_duplicate = TRUE;
+
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (is_duplicate)
+ {
+
+ APPL_TRACE_DEBUG2("bta_hl_is_a_duplicate_id app_id=%d is_duplicate=%d",
+ app_id, is_duplicate);
+ }
+#endif
+
+ return is_duplicate;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_find_avail_app_idx
+**
+** Description This function finds an available application control block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_avail_app_idx(UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+ {
+ if (!bta_hl_cb.acb[i].in_use)
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!found)
+ {
+ APPL_TRACE_DEBUG2("bta_hl_find_avail_app_idx found=%d app_idx=%d",
+ found, i);
+ }
+#endif
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_app_registration
+**
+** Description This function registers an HDP application MCAP and DP
+**
+** Returns tBTA_HL_STATUS -registration status
+**
+*******************************************************************************/
+tBTA_HL_STATUS bta_hl_app_registration(UINT8 app_idx)
+{
+ tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tMCA_REG reg;
+ tMCA_CS mca_cs;
+ UINT8 i, num_of_mdeps;
+
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("bta_hl_app_registration app_idx=%d", app_idx);
+#endif
+
+ reg.ctrl_psm = p_acb->ctrl_psm;
+ reg.data_psm = p_acb->data_psm;
+ reg.sec_mask = p_acb->sec_mask;
+ reg.rsp_tout = BTA_HL_MCAP_RSP_TOUT;
+
+ if ( (p_acb->app_handle = (tBTA_HL_APP_HANDLE) MCA_Register(®, bta_hl_mcap_ctrl_cback))!=0)
+ {
+ mca_cs.type = MCA_TDEP_ECHO;
+ mca_cs.max_mdl = BTA_HL_NUM_MDLS_PER_MDEP;
+ mca_cs.p_data_cback = bta_hl_mcap_data_cback;
+
+ if (MCA_CreateDep((tMCA_HANDLE)p_acb->app_handle,
+ &(p_acb->sup_feature.mdep[0].mdep_id),
+ &mca_cs) == MCA_SUCCESS)
+ {
+ if (p_acb->sup_feature.mdep[0].mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+ {
+ status = BTA_HL_STATUS_MCAP_REG_FAIL;
+ APPL_TRACE_ERROR1("BAD MDEP ID for echo test mdep_id=%d",
+ p_acb->sup_feature.mdep[0].mdep_id );
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_MCAP_REG_FAIL;
+ APPL_TRACE_ERROR0("MCA_CreateDep for echo test(mdep_id=0) failed");
+ }
+
+
+ if ((status == BTA_HL_STATUS_OK) &&
+ bta_hl_co_get_num_of_mdep(p_acb->app_id, &num_of_mdeps))
+ {
+ p_acb->sup_feature.num_of_mdeps = num_of_mdeps+1;
+
+ for (i=1; i<p_acb->sup_feature.num_of_mdeps; i++)
+ {
+ mca_cs.type = MCA_TDEP_DATA;
+ mca_cs.max_mdl = BTA_HL_NUM_MDLS_PER_MDEP;
+ mca_cs.p_data_cback = bta_hl_mcap_data_cback;
+
+ if (MCA_CreateDep((tMCA_HANDLE)p_acb->app_handle,
+ &(p_acb->sup_feature.mdep[i].mdep_id), &mca_cs) == MCA_SUCCESS)
+ {
+ if (bta_hl_co_get_mdep_config(p_acb->app_id,
+ i,
+ p_acb->sup_feature.mdep[i].mdep_id,
+ &p_acb->sup_feature.mdep[i].mdep_cfg))
+ {
+ if (p_acb->sup_feature.mdep[i].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SOURCE)
+ {
+ p_acb->sup_feature.app_role_mask |= BTA_HL_MDEP_ROLE_MASK_SOURCE;
+ }
+ else if (p_acb->sup_feature.mdep[i].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SINK)
+ {
+ p_acb->sup_feature.app_role_mask |= BTA_HL_MDEP_ROLE_MASK_SINK;
+ }
+ else
+ {
+ status = BTA_HL_STATUS_MDEP_CO_FAIL;
+ break;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_MDEP_CO_FAIL;
+ break;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_MCAP_REG_FAIL;
+ break;
+ }
+ }
+
+
+
+ if ((status == BTA_HL_STATUS_OK) &&
+ (p_acb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE))
+ {
+ /* this is a source only applciation */
+ p_acb->sup_feature.advertize_source_sdp =
+ bta_hl_co_advrtise_source_sdp(p_acb->app_id);
+ }
+
+ if ((status == BTA_HL_STATUS_OK)&&
+ (!bta_hl_co_get_echo_config(p_acb->app_id, &p_acb->sup_feature.echo_cfg)))
+ {
+ status = BTA_HL_STATUS_ECHO_CO_FAIL;
+ }
+
+ if ((status == BTA_HL_STATUS_OK)&&
+ (!bta_hl_co_load_mdl_config(p_acb->app_id, BTA_HL_NUM_MDL_CFGS, &p_acb->mdl_cfg[0])))
+ {
+ status = BTA_HL_STATUS_MDL_CFG_CO_FAIL;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_MDEP_CO_FAIL;
+ }
+ }
+ else
+ {
+ status = BTA_HL_STATUS_MCAP_REG_FAIL;
+ }
+
+ if (status == BTA_HL_STATUS_OK)
+ {
+ status = bta_hl_sdp_register(app_idx);
+ }
+
+ return status;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_discard_data
+**
+** Description This function discard an HDP event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_discard_data(UINT16 event, tBTA_HL_DATA *p_data)
+{
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_ERROR1("BTA HL Discard event=%s",bta_hl_evt_code(event));
+
+#endif
+
+ switch (event)
+ {
+ case BTA_HL_API_SEND_DATA_EVT:
+ break;
+
+ case BTA_HL_MCA_RCV_DATA_EVT:
+ utl_freebuf((void**)&p_data->mca_rcv_data_evt.p_pkt);
+ break;
+
+ default:
+ /*Nothing to free*/
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_save_mdl_cfg
+**
+** Description This function saves the MDL configuration
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_save_mdl_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx )
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ UINT8 mdl_cfg_idx;
+ tBTA_HL_MDL_ID mdl_id;
+ BOOLEAN found=TRUE;
+ tBTA_HL_MDL_CFG mdl_cfg;
+ tBTA_HL_MDEP *p_mdep_cfg;
+ tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
+ UINT8 time_val;
+ mdl_id = p_dcb->mdl_id;
+ if (!bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, mdl_id, &mdl_cfg_idx))
+ {
+ if (!bta_hl_find_avail_mdl_cfg_idx(app_idx, mcl_idx, &mdl_cfg_idx))
+ {
+ APPL_TRACE_ERROR0("No space to save the MDL config");
+ found= FALSE; /*no space available*/
+ }
+ }
+
+ if (found)
+ {
+ bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg);
+ if (!bta_hl_get_cur_time(app_idx, &time_val ))
+ {
+ bta_hl_compact_mdl_cfg_time(app_idx);
+ bta_hl_get_cur_time(app_idx, &time_val);
+ }
+ mdl_cfg.active = TRUE;
+ mdl_cfg.time = time_val;
+ mdl_cfg.mdl_id = p_dcb->mdl_id;
+ mdl_cfg.dch_mode = p_dcb->dch_mode;
+ mdl_cfg.mtu = l2cap_cfg.mtu;
+ mdl_cfg.fcs = l2cap_cfg.fcs;
+
+ bdcpy(mdl_cfg.peer_bd_addr, p_mcb->bd_addr);
+ mdl_cfg.local_mdep_id= p_dcb->local_mdep_id;
+ p_mdep_cfg = &p_acb->sup_feature.mdep[p_dcb->local_mdep_cfg_idx];
+ mdl_cfg.local_mdep_role= p_mdep_cfg->mdep_cfg.mdep_role;
+ memcpy(&p_acb->mdl_cfg[mdl_cfg_idx], &mdl_cfg, sizeof(tBTA_HL_MDL_CFG));
+ bta_hl_co_save_mdl(p_acb->app_id, mdl_cfg_idx, &mdl_cfg);
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (found)
+ {
+ if (p_dcb->mtu != l2cap_cfg.mtu)
+ {
+ APPL_TRACE_WARNING2("MCAP and L2CAP peer mtu size out of sync from MCAP mtu=%d from l2cap mtu=%d",
+ p_dcb->mtu, l2cap_cfg.mtu);
+ }
+ APPL_TRACE_DEBUG1("bta_hl_save_mdl_cfg saved=%d", found);
+ APPL_TRACE_DEBUG4("Saved. L2cap cfg mdl_id=%d mtu=%d fcs=%d dch_mode=%d",
+ mdl_cfg.mdl_id, mdl_cfg.mtu, mdl_cfg.fcs, mdl_cfg.dch_mode);
+ }
+#endif
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_set_dch_chan_cfg
+**
+** Description This function setups the L2CAP DCH channel configuration
+**
+** Returns void
+*******************************************************************************/
+void bta_hl_set_dch_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,tBTA_HL_DATA *p_data)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ UINT8 l2cap_mode = L2CAP_FCR_ERTM_MODE;
+ tBTA_HL_SUP_FEATURE *p_sup_feature= &p_acb->sup_feature;
+ UINT8 local_mdep_cfg_idx = p_dcb->local_mdep_cfg_idx;
+
+ switch (p_dcb->dch_oper)
+ {
+ case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+ case BTA_HL_DCH_OP_REMOTE_RECONNECT:
+ if (p_dcb->dch_mode == BTA_HL_DCH_MODE_STREAMING)
+ l2cap_mode = L2CAP_FCR_STREAM_MODE;
+ break;
+ case BTA_HL_DCH_OP_LOCAL_OPEN:
+ if (p_data->mca_evt.mca_data.create_cfm.cfg == BTA_HL_DCH_CFG_STREAMING)
+ l2cap_mode = L2CAP_FCR_STREAM_MODE;
+ break;
+ case BTA_HL_DCH_OP_REMOTE_OPEN:
+ if (p_dcb->local_cfg == BTA_HL_DCH_CFG_STREAMING )
+ l2cap_mode = L2CAP_FCR_STREAM_MODE;
+ break;
+ default:
+ APPL_TRACE_ERROR1("Invalid dch oper=%d for set dch chan cfg", p_dcb->dch_oper);
+ break;
+ }
+ p_dcb->chnl_cfg.fcr_opt.mode = l2cap_mode;
+ p_dcb->chnl_cfg.fcr_opt.mps = bta_hl_set_mps(p_dcb->max_rx_apdu_size);
+ p_dcb->chnl_cfg.fcr_opt.tx_win_sz = bta_hl_set_tx_win_size(p_dcb->max_rx_apdu_size,
+ p_dcb->chnl_cfg.fcr_opt.mps);
+ p_dcb->chnl_cfg.fcr_opt.max_transmit= BTA_HL_L2C_MAX_TRANSMIT;
+ p_dcb->chnl_cfg.fcr_opt.rtrans_tout = BTA_HL_L2C_RTRANS_TOUT;
+ p_dcb->chnl_cfg.fcr_opt.mon_tout = BTA_HL_L2C_MON_TOUT;
+
+ p_dcb->chnl_cfg.user_rx_pool_id = bta_hl_set_user_rx_pool_id(p_dcb->max_rx_apdu_size);
+ p_dcb->chnl_cfg.user_tx_pool_id = bta_hl_set_user_tx_pool_id(p_dcb->max_tx_apdu_size);
+ p_dcb->chnl_cfg.fcr_rx_pool_id = BTA_HL_L2C_FCR_RX_POOL_ID;
+ p_dcb->chnl_cfg.fcr_tx_pool_id = BTA_HL_L2C_FCR_TX_POOL_ID;
+ p_dcb->chnl_cfg.data_mtu = p_dcb->max_rx_apdu_size;
+
+ p_dcb->chnl_cfg.fcs = BTA_HL_MCA_NO_FCS;
+ if (local_mdep_cfg_idx != BTA_HL_ECHO_TEST_MDEP_CFG_IDX)
+ {
+ if (p_sup_feature->mdep[local_mdep_cfg_idx].mdep_cfg.mdep_role ==
+ BTA_HL_MDEP_ROLE_SOURCE)
+ {
+ p_dcb->chnl_cfg.fcs = BTA_HL_DEFAULT_SOURCE_FCS;
+ }
+ }
+ else
+ {
+ p_dcb->chnl_cfg.fcs = BTA_HL_MCA_USE_FCS;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("L2CAP Params l2cap_mode[3-ERTM 4-STREAM]=%d", l2cap_mode);
+ APPL_TRACE_DEBUG2("Use FCS =%s mtu=%d", ((p_dcb->chnl_cfg.fcs & 1)?"YES":"NO"),
+ p_dcb->chnl_cfg.data_mtu);
+ APPL_TRACE_DEBUG5("tx_win_sz=%d, max_transmit=%d, rtrans_tout=%d, mon_tout=%d, mps=%d",
+ p_dcb->chnl_cfg.fcr_opt.tx_win_sz,
+ p_dcb->chnl_cfg.fcr_opt.max_transmit,
+ p_dcb->chnl_cfg.fcr_opt.rtrans_tout,
+ p_dcb->chnl_cfg.fcr_opt.mon_tout,
+ p_dcb->chnl_cfg.fcr_opt.mps);
+
+ APPL_TRACE_DEBUG4("USER rx_pool_id=%d, tx_pool_id=%d, FCR rx_pool_id=%d, tx_pool_id=%d",
+ p_dcb->chnl_cfg.user_rx_pool_id,
+ p_dcb->chnl_cfg.user_tx_pool_id,
+ p_dcb->chnl_cfg.fcr_rx_pool_id,
+ p_dcb->chnl_cfg.fcr_tx_pool_id);
+
+#endif
+
+
+
+
+
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_get_l2cap_cfg
+**
+** Description This function get the current L2CAP channel configuration
+**
+** Returns BOOLEAN - TRUE - operation is successful
+*******************************************************************************/
+BOOLEAN bta_hl_get_l2cap_cfg(tBTA_HL_MDL_HANDLE mdl_hnd, tBTA_HL_L2CAP_CFG_INFO *p_cfg)
+{
+ BOOLEAN success = FALSE;
+ UINT16 lcid;
+ tL2CAP_CFG_INFO *p_our_cfg;
+ tL2CAP_CH_CFG_BITS our_cfg_bits;
+ tL2CAP_CFG_INFO *p_peer_cfg;
+ tL2CAP_CH_CFG_BITS peer_cfg_bits;
+
+ lcid = MCA_GetL2CapChannel((tMCA_DL) mdl_hnd);
+ if ( lcid &&
+ L2CA_GetCurrentConfig(lcid, &p_our_cfg, &our_cfg_bits, &p_peer_cfg,
+ &peer_cfg_bits))
+ {
+ p_cfg->fcs = BTA_HL_MCA_NO_FCS;
+ if (our_cfg_bits & L2CAP_CH_CFG_MASK_FCS)
+ {
+ p_cfg->fcs |= p_our_cfg->fcs;
+ }
+ else
+ {
+ p_cfg->fcs = BTA_HL_MCA_USE_FCS;
+ }
+
+ if (p_cfg->fcs != BTA_HL_MCA_USE_FCS )
+ {
+ if (peer_cfg_bits & L2CAP_CH_CFG_MASK_FCS)
+ {
+ p_cfg->fcs |= p_peer_cfg->fcs;
+ }
+ else
+ {
+ p_cfg->fcs = BTA_HL_MCA_USE_FCS;
+ }
+ }
+
+ p_cfg->mtu =0;
+ if (peer_cfg_bits & L2CAP_CH_CFG_MASK_MTU)
+ {
+ p_cfg->mtu = p_peer_cfg->mtu;
+ }
+ else
+ {
+ p_cfg->mtu = L2CAP_DEFAULT_MTU;
+ }
+ success = TRUE;
+ }
+
+#if BTA_HL_DEBUG == TRUE
+ if (!success)
+ {
+ APPL_TRACE_DEBUG3("bta_hl_get_l2cap_cfg success=%d mdl=%d lcid=%d", success, mdl_hnd, lcid);
+ APPL_TRACE_DEBUG2("l2cap mtu=%d fcs=%d", p_cfg->mtu, p_cfg->fcs);
+ }
+#endif
+
+ return success;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_validate_chan_cfg
+**
+** Description This function validates the L2CAP channel configuration
+**
+** Returns BOOLEAN - TRUE - validation is successful
+*******************************************************************************/
+BOOLEAN bta_hl_validate_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ BOOLEAN success = FALSE;
+ UINT8 mdl_cfg_idx;
+ tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
+
+
+ if (bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg) &&
+ bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_dcb->mdl_id, &mdl_cfg_idx))
+ {
+ if ((p_acb->mdl_cfg[mdl_cfg_idx].mtu <= l2cap_cfg.mtu) &&
+ (p_acb->mdl_cfg[mdl_cfg_idx].fcs == l2cap_cfg.fcs) &&
+ (p_acb->mdl_cfg[mdl_cfg_idx].dch_mode == p_dcb->dch_mode))
+ {
+ success = TRUE;
+ }
+ }
+
+
+#if BTA_HL_DEBUG == TRUE
+
+ if (p_dcb->mtu != l2cap_cfg.mtu)
+ {
+ APPL_TRACE_WARNING2("MCAP and L2CAP peer mtu size out of sync from MCAP mtu=%d from l2cap mtu=%d",
+ p_dcb->mtu, l2cap_cfg.mtu);
+ }
+
+ if (!success)
+ {
+ APPL_TRACE_DEBUG4("bta_hl_validate_chan_cfg success=%d app_idx=%d mcl_idx=%d mdl_idx=%d",success, app_idx, mcl_idx, mdl_idx);
+ APPL_TRACE_DEBUG3("Cur. L2cap cfg mtu=%d fcs=%d dch_mode=%d", l2cap_cfg.mtu, l2cap_cfg.fcs, p_dcb->dch_mode);
+ APPL_TRACE_DEBUG3("From saved: L2cap cfg mtu=%d fcs=%d dch_mode=%d", p_acb->mdl_cfg[mdl_cfg_idx].mtu,
+ p_acb->mdl_cfg[mdl_cfg_idx].fcs , p_acb->mdl_cfg[mdl_cfg_idx].dch_mode);
+ }
+#endif
+
+ return success;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_is_cong_on
+**
+** Description This function checks whether the congestion condition is on or not
+**
+** Returns BOOLEAN - TRUE DCH is congested
+** FALSE not congested
+**
+*******************************************************************************/
+BOOLEAN bta_hl_is_cong_on(UINT8 app_id, BD_ADDR bd_addr, tBTA_HL_MDL_ID mdl_id)
+
+{
+ tBTA_HL_MDL_CB *p_dcb;
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ BOOLEAN cong_status = TRUE;
+
+ if (bta_hl_find_app_idx(app_id, &app_idx))
+ {
+ if (bta_hl_find_mcl_idx(app_idx, bd_addr, &mcl_idx ))
+ {
+ if (bta_hl_find_mdl_idx(app_idx, mcl_idx, mdl_id, &mdl_idx ))
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ cong_status = p_dcb->cong;
+ }
+ }
+ }
+
+ return cong_status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_check_cch_close
+**
+** Description This function checks whether there is a pending CCH close request
+** or not
+**
+** Returns void
+*******************************************************************************/
+void bta_hl_check_cch_close(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data, BOOLEAN check_dch_setup )
+{
+ tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ tBTA_HL_MDL_CB *p_dcb;
+ UINT8 mdl_idx;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG1("bta_hl_check_cch_close cch_close_dch_oper=%d",p_mcb->cch_close_dch_oper );
+#endif
+
+ if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE)
+ {
+ if (check_dch_setup && bta_hl_find_dch_setup_mdl_idx(app_idx, mcl_idx, &mdl_idx))
+ {
+ p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+ if (!p_mcb->rsp_tout)
+ {
+ p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_ABORT;
+
+ if (!p_dcb->abort_oper)
+ {
+ p_dcb->abort_oper |= BTA_HL_ABORT_CCH_CLOSE_MASK;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT, p_data);
+ }
+ }
+ else
+ {
+ p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_CLOSE;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+ }
+ }
+ else if (bta_hl_find_an_active_mdl_idx(app_idx, mcl_idx,&mdl_idx))
+ {
+ p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_CLOSE;
+ bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT, p_data);
+ }
+ else
+ {
+ p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_NONE;
+ bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_clean_app
+**
+** Description Cleans up the HDP application resources and control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_clean_app(UINT8 app_idx)
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ int i, num_act_apps=0;
+
+#if BTA_HL_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_hl_clean_app");
+#endif
+ MCA_Deregister((tMCA_HANDLE)p_acb->app_handle);
+
+ if (p_acb->sdp_handle) SDP_DeleteRecord(p_acb->sdp_handle);
+
+ memset((void *) p_acb, 0, sizeof(tBTA_HL_APP_CB));
+
+ /* check any application is still active */
+ for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(i);
+ if (p_acb->in_use) num_act_apps++;
+ }
+
+ if (!num_act_apps)
+ {
+ bta_sys_remove_uuid(UUID_SERVCLASS_HDP_PROFILE);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_check_deregistration
+**
+** Description This function checks whether there is a pending deregistration
+** request or not
+**
+** Returns void
+*******************************************************************************/
+void bta_hl_check_deregistration(UINT8 app_idx, tBTA_HL_DATA *p_data )
+{
+ tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ tBTA_HL_MCL_CB *p_mcb;
+ UINT8 mcl_idx;
+ tBTA_HL evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_check_deregistration");
+#endif
+
+ if (p_acb->deregistering)
+ {
+ if (bta_hl_find_an_in_use_mcl_idx(app_idx, &mcl_idx))
+ {
+ p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+ if (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE)
+ {
+ p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
+ bta_hl_check_cch_close(app_idx,mcl_idx,p_data, TRUE);
+ }
+ }
+ else
+ {
+ /* all cchs are closed */
+ evt_data.dereg_cfm.app_handle = p_acb->app_handle;
+ evt_data.dereg_cfm.status = BTA_HL_STATUS_OK;
+ p_acb->p_cback(BTA_HL_DEREGISTER_CFM_EVT, (tBTA_HL *) &evt_data );
+ bta_hl_clean_app(app_idx);
+ bta_hl_check_disable(p_data);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_check_disable
+**
+** Description This function checks whether there is a pending disable
+** request or not
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hl_check_disable(tBTA_HL_DATA *p_data )
+{
+ tBTA_HL_CB *p_cb= &bta_hl_cb;
+ tBTA_HL_APP_CB *p_acb;
+ UINT8 app_idx;
+ tBTA_HL_CTRL evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+ APPL_TRACE_DEBUG0("bta_hl_check_disable");
+#endif
+
+ if (bta_hl_cb.disabling)
+ {
+ if (bta_hl_find_an_in_use_app_idx(&app_idx))
+ {
+ p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+ if (!p_acb->deregistering)
+ {
+ p_acb->deregistering = TRUE;
+ bta_hl_check_deregistration(app_idx, p_data);
+ }
+ }
+ else
+ {
+ /* all apps are deregistered */
+ bta_sys_deregister(BTA_ID_HL);
+ evt_data.disable_cfm.status = BTA_HL_STATUS_OK;
+ if (p_cb->p_ctrl_cback) p_cb->p_ctrl_cback(BTA_HL_CTRL_DISABLE_CFM_EVT, (tBTA_HL_CTRL *) &evt_data);
+ memset((void *) p_cb, 0, sizeof(tBTA_HL_CB));
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_abort_cfm
+**
+** Description This function builds the abort confirmation event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_abort_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status)
+{
+ p_evt_data->dch_abort_cfm.status = status;
+ p_evt_data->dch_abort_cfm.mcl_handle = mcl_handle;
+ p_evt_data->dch_abort_cfm.app_handle = app_handle;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_abort_ind
+**
+** Description This function builds the abort indication event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_abort_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle)
+{
+ p_evt_data->dch_abort_ind.mcl_handle = mcl_handle;
+ p_evt_data->dch_abort_ind.app_handle = app_handle;
+}
+/*******************************************************************************
+**
+** Function bta_hl_build_close_cfm
+**
+** Description This function builds the close confirmation event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_dch_close_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_STATUS status)
+{
+ p_evt_data->dch_close_cfm.status = status;
+ p_evt_data->dch_close_cfm.mdl_handle = mdl_handle;
+ p_evt_data->dch_close_cfm.mcl_handle = mcl_handle;
+ p_evt_data->dch_close_cfm.app_handle = app_handle;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_dch_close_ind
+**
+** Description This function builds the close indication event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_dch_close_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle,
+ BOOLEAN intentional)
+{
+ p_evt_data->dch_close_ind.mdl_handle = mdl_handle;
+ p_evt_data->dch_close_ind.mcl_handle = mcl_handle;
+ p_evt_data->dch_close_ind.app_handle = app_handle;
+ p_evt_data->dch_close_ind.intentional = intentional;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_send_data_cfm
+**
+** Description This function builds the send data confirmation event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_send_data_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_STATUS status )
+{
+
+ p_evt_data->dch_send_data_cfm.mdl_handle = mdl_handle;
+ p_evt_data->dch_send_data_cfm.mcl_handle = mcl_handle;
+ p_evt_data->dch_send_data_cfm.app_handle = app_handle;
+ p_evt_data->dch_send_data_cfm.status = status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_rcv_data_ind
+**
+** Description This function builds the received data indication event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_rcv_data_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle)
+{
+ p_evt_data->dch_rcv_data_ind.mdl_handle = mdl_handle;
+ p_evt_data->dch_rcv_data_ind.mcl_handle = mcl_handle;
+ p_evt_data->dch_rcv_data_ind.app_handle = app_handle;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_build_cch_open_cfm
+**
+** Description This function builds the CCH open confirmation event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_cch_open_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ BD_ADDR bd_addr,
+ tBTA_HL_STATUS status )
+{
+
+ p_evt_data->cch_open_cfm.app_handle = app_handle;
+ p_evt_data->cch_open_cfm.mcl_handle = mcl_handle;
+ bdcpy(p_evt_data->cch_open_cfm.bd_addr, bd_addr);
+ p_evt_data->cch_open_cfm.status = status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_cch_open_ind
+**
+** Description This function builds the CCH open indication event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_cch_open_ind(tBTA_HL *p_evt_data, tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ BD_ADDR bd_addr )
+{
+
+ p_evt_data->cch_open_ind.app_handle = app_handle;
+ p_evt_data->cch_open_ind.mcl_handle = mcl_handle;
+ bdcpy(p_evt_data->cch_open_ind.bd_addr, bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_cch_close_cfm
+**
+** Description This function builds the CCH close confirmation event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_cch_close_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status )
+{
+ p_evt_data->cch_close_cfm.mcl_handle = mcl_handle;
+ p_evt_data->cch_close_cfm.app_handle = app_handle;
+ p_evt_data->cch_close_cfm.status = status;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_build_cch_close_ind
+**
+** Description This function builds the CCH colse indication event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_cch_close_ind(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ BOOLEAN intentional)
+{
+ p_evt_data->cch_close_ind.mcl_handle = mcl_handle;
+ p_evt_data->cch_close_ind.app_handle = app_handle;
+ p_evt_data->cch_close_ind.intentional = intentional;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_dch_open_cfm
+**
+** Description This function builds the DCH open confirmation event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_dch_open_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_MDEP_ID local_mdep_id,
+ tBTA_HL_MDL_ID mdl_id,
+ tBTA_HL_DCH_MODE dch_mode,
+ BOOLEAN first_reliable,
+ UINT16 mtu,
+ tBTA_HL_STATUS status)
+
+{
+ p_evt_data->dch_open_cfm.mdl_handle = mdl_handle;
+ p_evt_data->dch_open_cfm.mcl_handle = mcl_handle;
+ p_evt_data->dch_open_cfm.app_handle = app_handle;
+ p_evt_data->dch_open_cfm.local_mdep_id = local_mdep_id;
+ p_evt_data->dch_open_cfm.mdl_id = mdl_id;
+ p_evt_data->dch_open_cfm.dch_mode = dch_mode;
+ p_evt_data->dch_open_cfm.first_reliable = first_reliable;
+ p_evt_data->dch_open_cfm.mtu = mtu;
+ p_evt_data->dch_open_cfm.status = status;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_build_sdp_query_cfm
+**
+** Description This function builds the SDP query indication event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_sdp_query_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ BD_ADDR bd_addr,
+ tBTA_HL_SDP *p_sdp,
+ tBTA_HL_STATUS status)
+
+{
+ p_evt_data->sdp_query_cfm.app_handle = app_handle;
+ bdcpy(p_evt_data->sdp_query_cfm.bd_addr, bd_addr);
+ p_evt_data->sdp_query_cfm.p_sdp = p_sdp;
+ p_evt_data->sdp_query_cfm.status = status;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_build_delete_mdl_cfm
+**
+** Description This function builds the delete MDL confirmation event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_delete_mdl_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_ID mdl_id,
+ tBTA_HL_STATUS status)
+
+{
+ p_evt_data->delete_mdl_cfm.mcl_handle = mcl_handle;
+ p_evt_data->delete_mdl_cfm.app_handle = app_handle;
+ p_evt_data->delete_mdl_cfm.mdl_id = mdl_id;
+ p_evt_data->delete_mdl_cfm.status = status;
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_build_echo_test_cfm
+**
+** Description This function builds the echo test confirmation event data
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_hl_build_echo_test_cfm(tBTA_HL *p_evt_data,
+ tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status )
+{
+ p_evt_data->echo_test_cfm.mcl_handle = mcl_handle;
+ p_evt_data->echo_test_cfm.app_handle = app_handle;
+ p_evt_data->echo_test_cfm.status = status;
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if (BTA_HL_DEBUG == TRUE)
+
+/*******************************************************************************
+**
+** Function bta_hl_status_code
+**
+** Description get the status string pointer
+**
+** Returns char * - status string pointer
+**
+*******************************************************************************/
+char *bta_hl_status_code(tBTA_HL_STATUS status)
+{
+ switch (status)
+ {
+ case BTA_HL_STATUS_OK:
+ return "BTA_HL_STATUS_OK";
+ case BTA_HL_STATUS_FAIL:
+ return "BTA_HL_STATUS_FAIL";
+ case BTA_HL_STATUS_ABORTED:
+ return "BTA_HL_STATUS_ABORTED";
+ case BTA_HL_STATUS_NO_RESOURCE:
+ return "BTA_HL_STATUS_NO_RESOURCE";
+ case BTA_HL_STATUS_LAST_ITEM:
+ return "BTA_HL_STATUS_LAST_ITEM";
+ case BTA_HL_STATUS_DUPLICATE_APP_ID:
+ return "BTA_HL_STATUS_DUPLICATE_APP_ID";
+ case BTA_HL_STATUS_INVALID_APP_HANDLE:
+ return "BTA_HL_STATUS_INVALID_APP_HANDLE";
+ case BTA_HL_STATUS_INVALID_MCL_HANDLE:
+ return "BTA_HL_STATUS_INVALID_MCL_HANDLE";
+ case BTA_HL_STATUS_MCAP_REG_FAIL:
+ return "BTA_HL_STATUS_MCAP_REG_FAIL";
+ case BTA_HL_STATUS_MDEP_CO_FAIL:
+ return "BTA_HL_STATUS_MDEP_CO_FAIL";
+ case BTA_HL_STATUS_ECHO_CO_FAIL:
+ return "BTA_HL_STATUS_ECHO_CO_FAIL";
+ case BTA_HL_STATUS_MDL_CFG_CO_FAIL:
+ return "BTA_HL_STATUS_MDL_CFG_CO_FAIL";
+ case BTA_HL_STATUS_SDP_NO_RESOURCE:
+ return "BTA_HL_STATUS_SDP_NO_RESOURCE";
+ case BTA_HL_STATUS_SDP_FAIL:
+ return "BTA_HL_STATUS_SDP_FAIL";
+ case BTA_HL_STATUS_NO_CCH:
+ return "BTA_HL_STATUS_NO_CCH";
+ case BTA_HL_STATUS_NO_MCL:
+ return "BTA_HL_STATUS_NO_MCL";
+
+ case BTA_HL_STATUS_NO_FIRST_RELIABLE:
+ return "BTA_HL_STATUS_NO_FIRST_RELIABLE";
+ case BTA_HL_STATUS_INVALID_DCH_CFG:
+ return "BTA_HL_STATUS_INVALID_DCH_CFG";
+ case BTA_HL_STATUS_INVALID_BD_ADDR:
+ return "BTA_HL_STATUS_INVALID_BD_ADDR";
+ case BTA_HL_STATUS_INVALID_RECONNECT_CFG:
+ return "BTA_HL_STATUS_INVALID_RECONNECT_CFG";
+ case BTA_HL_STATUS_ECHO_TEST_BUSY:
+ return "BTA_HL_STATUS_ECHO_TEST_BUSY";
+ case BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID:
+ return "BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID";
+ case BTA_HL_STATUS_INVALID_MDL_ID:
+ return "BTA_HL_STATUS_INVALID_MDL_ID";
+ case BTA_HL_STATUS_NO_MDL_ID_FOUND:
+ return "BTA_HL_STATUS_NO_MDL_ID_FOUND";
+ case BTA_HL_STATUS_DCH_BUSY:
+ return "BTA_HL_STATUS_DCH_BUSY";
+ default:
+ return "Unknown status code";
+ }
+}
+/*******************************************************************************
+**
+** Function bta_hl_evt_code
+**
+** Description Maps HL event code to the corresponding event string
+**
+** Returns string pointer for the associated event name
+**
+*******************************************************************************/
+char *bta_hl_evt_code(tBTA_HL_INT_EVT evt_code)
+{
+ switch (evt_code)
+ {
+ case BTA_HL_CCH_OPEN_EVT:
+ return "BTA_HL_CCH_OPEN_EVT";
+ case BTA_HL_CCH_SDP_OK_EVT:
+ return "BTA_HL_CCH_SDP_OK_EVT";
+ case BTA_HL_CCH_SDP_FAIL_EVT:
+ return "BTA_HL_CCH_SDP_FAIL_EVT";
+ case BTA_HL_MCA_CONNECT_IND_EVT:
+ return "BTA_HL_MCA_CONNECT_IND_EVT";
+ case BTA_HL_MCA_DISCONNECT_IND_EVT:
+ return "BTA_HL_MCA_DISCONNECT_IND_EVT";
+
+ case BTA_HL_CCH_CLOSE_EVT:
+ return "BTA_HL_CCH_CLOSE_EVT";
+ case BTA_HL_CCH_CLOSE_CMPL_EVT:
+ return "BTA_HL_CCH_CLOSE_CMPL_EVT";
+ case BTA_HL_DCH_OPEN_EVT:
+ return "BTA_HL_DCH_OPEN_EVT";
+ case BTA_HL_MCA_CREATE_IND_EVT:
+ return "BTA_HL_MCA_CREATE_IND_EVT";
+ case BTA_HL_MCA_CREATE_CFM_EVT:
+ return "BTA_HL_MCA_CREATE_CFM_EVT";
+ case BTA_HL_MCA_OPEN_IND_EVT:
+ return "BTA_HL_MCA_OPEN_IND_EVT";
+ case BTA_HL_MCA_OPEN_CFM_EVT:
+ return "BTA_HL_MCA_OPEN_CFM_EVT";
+ case BTA_HL_DCH_CLOSE_EVT:
+ return "BTA_HL_DCH_CLOSE_EVT";
+ case BTA_HL_MCA_CLOSE_IND_EVT:
+ return "BTA_HL_MCA_CLOSE_IND_EVT";
+ case BTA_HL_MCA_CLOSE_CFM_EVT:
+ return "BTA_HL_MCA_CLOSE_CFM_EVT";
+ case BTA_HL_API_SEND_DATA_EVT:
+ return "BTA_HL_API_SEND_DATA_EVT";
+ case BTA_HL_MCA_RCV_DATA_EVT:
+ return "BTA_HL_MCA_RCV_DATA_EVT";
+ case BTA_HL_DCH_CLOSE_CMPL_EVT:
+ return "BTA_HL_DCH_CLOSE_CMPL_EVT";
+
+ case BTA_HL_API_ENABLE_EVT:
+ return "BTA_HL_API_ENABLE_EVT";
+ case BTA_HL_API_DISABLE_EVT:
+ return "BTA_HL_API_DISABLE_EVT";
+ case BTA_HL_API_REGISTER_EVT:
+ return "BTA_HL_API_REGISTER_EVT";
+ case BTA_HL_API_DEREGISTER_EVT:
+ return "BTA_HL_API_DEREGISTER_EVT";
+
+ case BTA_HL_API_CCH_OPEN_EVT:
+ return "BTA_HL_API_CCH_OPEN_EVT";
+
+ case BTA_HL_API_CCH_CLOSE_EVT:
+ return "BTA_HL_API_CCH_CLOSE_EVT";
+ case BTA_HL_API_DCH_OPEN_EVT:
+ return "BTA_HL_API_DCH_OPEN_EVT";
+
+ case BTA_HL_API_DCH_RECONNECT_EVT:
+ return "BTA_HL_API_DCH_RECONNECT_EVT";
+ case BTA_HL_API_DCH_CLOSE_EVT:
+ return "BTA_HL_API_DCH_CLOSE_EVT";
+ case BTA_HL_API_DELETE_MDL_EVT:
+ return "BTA_HL_API_DELETE_MDL_EVT";
+ case BTA_HL_API_DCH_ABORT_EVT:
+ return "BTA_HL_API_DCH_ABORT_EVT";
+
+ case BTA_HL_DCH_RECONNECT_EVT:
+ return "BTA_HL_DCH_RECONNECT_EVT";
+ case BTA_HL_DCH_SDP_INIT_EVT:
+ return "BTA_HL_DCH_SDP_INIT_EVT";
+ case BTA_HL_DCH_SDP_FAIL_EVT:
+ return "BTA_HL_DCH_SDP_FAIL_EVT";
+ case BTA_HL_API_DCH_ECHO_TEST_EVT:
+ return "BTA_HL_API_DCH_ECHO_TEST_EVT";
+ case BTA_HL_DCH_CLOSE_ECHO_TEST_EVT:
+ return "BTA_HL_DCH_CLOSE_ECHO_TEST_EVT";
+ case BTA_HL_MCA_RECONNECT_IND_EVT:
+ return "BTA_HL_MCA_RECONNECT_IND_EVT";
+ case BTA_HL_MCA_RECONNECT_CFM_EVT:
+ return "BTA_HL_MCA_RECONNECT_CFM_EVT";
+ case BTA_HL_API_DCH_CREATE_RSP_EVT:
+ return "BTA_HL_API_DCH_CREATE_RSP_EVT";
+ case BTA_HL_DCH_ABORT_EVT:
+ return "BTA_HL_DCH_ABORT_EVT";
+ case BTA_HL_MCA_ABORT_IND_EVT:
+ return "BTA_HL_MCA_ABORT_IND_EVT";
+ case BTA_HL_MCA_ABORT_CFM_EVT:
+ return "BTA_HL_MCA_ABORT_CFM_EVT";
+ case BTA_HL_MCA_DELETE_IND_EVT:
+ return "BTA_HL_MCA_DELETE_IND_EVT";
+ case BTA_HL_MCA_DELETE_CFM_EVT:
+ return "BTA_HL_MCA_DELETE_CFM_EVT";
+ case BTA_HL_MCA_CONG_CHG_EVT:
+ return "BTA_HL_MCA_CONG_CHG_EVT";
+ case BTA_HL_CI_GET_TX_DATA_EVT:
+ return "BTA_HL_CI_GET_TX_DATA_EVT";
+ case BTA_HL_CI_PUT_RX_DATA_EVT:
+ return "BTA_HL_CI_PUT_RX_DATA_EVT";
+ case BTA_HL_CI_GET_ECHO_DATA_EVT:
+ return "BTA_HL_CI_GET_ECHO_DATA_EVT";
+ case BTA_HL_DCH_ECHO_TEST_EVT:
+ return "BTA_HL_DCH_ECHO_TEST_EVT";
+ case BTA_HL_CI_PUT_ECHO_DATA_EVT:
+ return "BTA_HL_CI_PUT_ECHO_DATA_EVT";
+ case BTA_HL_API_SDP_QUERY_EVT:
+ return "BTA_HL_API_SDP_QUERY_EVT";
+ case BTA_HL_SDP_QUERY_OK_EVT:
+ return "BTA_HL_SDP_QUERY_OK_EVT";
+ case BTA_HL_SDP_QUERY_FAIL_EVT:
+ return "BTA_HL_SDP_QUERY_FAIL_EVT";
+ case BTA_HL_MCA_RSP_TOUT_IND_EVT:
+ return "BTA_HL_MCA_RSP_TOUT_IND_EVT";
+
+ default:
+ return "Unknown HL event code";
+ }
+}
+
+#endif /* Debug Functions */
+#endif // HL_INCLUDED
+
+
+
+
+
+
+
+
diff --git a/bta/include/bd.h b/bta/include/bd.h
new file mode 100644
index 0000000..33c3de1
--- /dev/null
+++ b/bta/include/bd.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * BD address services.
+ *
+ ******************************************************************************/
+#ifndef BD_H
+#define BD_H
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* bd addr length and type */
+#ifndef BD_ADDR_LEN
+#define BD_ADDR_LEN 6
+typedef UINT8 BD_ADDR[BD_ADDR_LEN];
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* global constant for "any" bd addr */
+extern const BD_ADDR bd_addr_any;
+extern const BD_ADDR bd_addr_null;
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bdcpy
+**
+** Description Copy bd addr b to a.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bdcpy(BD_ADDR a, const BD_ADDR b);
+
+/*******************************************************************************
+**
+** Function bdcmp
+**
+** Description Compare bd addr b to a.
+**
+**
+** Returns Zero if b==a, nonzero otherwise (like memcmp).
+**
+*******************************************************************************/
+extern int bdcmp(const BD_ADDR a, const BD_ADDR b);
+
+/*******************************************************************************
+**
+** Function bdcmpany
+**
+** Description Compare bd addr to "any" bd addr.
+**
+**
+** Returns Zero if a equals bd_addr_any.
+**
+*******************************************************************************/
+extern int bdcmpany(const BD_ADDR a);
+
+/*******************************************************************************
+**
+** Function bdsetany
+**
+** Description Set bd addr to "any" bd addr.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bdsetany(BD_ADDR a);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BD_H */
+
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
new file mode 100644
index 0000000..f16687c
--- /dev/null
+++ b/bta/include/bta_ag_api.h
@@ -0,0 +1,514 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the audio gateway (AG) subsystem
+ * of BTA, Broadcom's Bluetooth application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_API_H
+#define BTA_AG_API_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* AG feature masks */
+#define BTA_AG_FEAT_3WAY 0x00000001 /* Three-way calling */
+#define BTA_AG_FEAT_ECNR 0x00000002 /* Echo cancellation and/or noise reduction */
+#define BTA_AG_FEAT_VREC 0x00000004 /* Voice recognition */
+#define BTA_AG_FEAT_INBAND 0x00000008 /* In-band ring tone */
+#define BTA_AG_FEAT_VTAG 0x00000010 /* Attach a phone number to a voice tag */
+#define BTA_AG_FEAT_REJECT 0x00000020 /* Ability to reject incoming call */
+#define BTA_AG_FEAT_ECS 0x00000040 /* Enhanced Call Status */
+#define BTA_AG_FEAT_ECC 0x00000080 /* Enhanced Call Control */
+#define BTA_AG_FEAT_EXTERR 0x00000100 /* Extended error codes */
+#define BTA_AG_FEAT_CODEC 0x00000200 /* Codec Negotiation */
+#define BTA_AG_FEAT_VOIP 0x00000400 /* VoIP call */
+/* Proprietary features: using 31 ~ 16 bits */
+#define BTA_AG_FEAT_BTRH 0x00010000 /* CCAP incoming call hold */
+#define BTA_AG_FEAT_UNAT 0x00020000 /* Pass unknown AT commands to application */
+#define BTA_AG_FEAT_NOSCO 0x00040000 /* No SCO control performed by BTA AG */
+#define BTA_AG_FEAT_NO_ESCO 0x00080000 /* Do not allow or use eSCO */
+
+typedef UINT32 tBTA_AG_FEAT;
+
+/* AG parse mode */
+#define BTA_AG_PARSE 0 /* Perform AT command parsing in AG */
+#define BTA_AG_PASS_THROUGH 1 /* Pass data directly to phoneÂ’s AT command interpreter */
+
+typedef UINT8 tBTA_AG_PARSE_MODE;
+
+/* AG open status */
+#define BTA_AG_SUCCESS 0 /* Connection successfully opened */
+#define BTA_AG_FAIL_SDP 1 /* Open failed due to SDP */
+#define BTA_AG_FAIL_RFCOMM 2 /* Open failed due to RFCOMM */
+#define BTA_AG_FAIL_RESOURCES 3 /* out of resources failure */
+
+typedef UINT8 tBTA_AG_STATUS;
+
+/* handle values used with BTA_AgResult */
+#define BTA_AG_HANDLE_NONE 0
+#define BTA_AG_HANDLE_ALL 0xFFFF
+/* It is safe to use the same value as BTA_AG_HANDLE_ALL
+ * HANDLE_ALL is used for delivering indication
+ * SCO_NO_CHANGE is used for changing sco behavior
+ * They donot interfere with each other
+ */
+#define BTA_AG_HANDLE_SCO_NO_CHANGE 0xFFFF
+
+/* AG result codes used with BTA_AgResult */
+#define BTA_AG_SPK_RES 0 /* Update speaker volume */
+#define BTA_AG_MIC_RES 1 /* Update microphone volume */
+#define BTA_AG_INBAND_RING_RES 2 /* Update inband ring state */
+#define BTA_AG_CIND_RES 3 /* Send indicator response for AT+CIND */
+#define BTA_AG_BINP_RES 4 /* Send phone number for voice tag for AT+BINP */
+#define BTA_AG_IND_RES 5 /* Update an indicator value */
+#define BTA_AG_BVRA_RES 6 /* Update voice recognition state */
+#define BTA_AG_CNUM_RES 7 /* Send subscriber number response for AT+CNUM */
+#define BTA_AG_BTRH_RES 8 /* Send CCAP incoming call hold */
+#define BTA_AG_CLCC_RES 9 /* Query list of calls */
+#define BTA_AG_COPS_RES 10 /* Read network operator */
+#define BTA_AG_IN_CALL_RES 11 /* Indicate incoming phone call */
+#define BTA_AG_IN_CALL_CONN_RES 12 /* Incoming phone call connected */
+#define BTA_AG_CALL_WAIT_RES 13 /* Call waiting notification */
+#define BTA_AG_OUT_CALL_ORIG_RES 14 /* Outgoing phone call origination */
+#define BTA_AG_OUT_CALL_ALERT_RES 15 /* Outgoing phone call alerting remote party */
+#define BTA_AG_OUT_CALL_CONN_RES 16 /* Outgoing phone call connected */
+#define BTA_AG_CALL_CANCEL_RES 17 /* Incoming/outgoing 3-way canceled before connected */
+#define BTA_AG_END_CALL_RES 18 /* End call */
+#define BTA_AG_IN_CALL_HELD_RES 19 /* Incoming call held */
+#define BTA_AG_UNAT_RES 20 /* Response to unknown AT command event */
+
+typedef UINT8 tBTA_AG_RES;
+
+/* HFP peer features */
+#define BTA_AG_PEER_FEAT_ECNR 0x0001 /* Echo cancellation and/or noise reduction */
+#define BTA_AG_PEER_FEAT_3WAY 0x0002 /* Call waiting and three-way calling */
+#define BTA_AG_PEER_FEAT_CLI 0x0004 /* Caller ID presentation capability */
+#define BTA_AG_PEER_FEAT_VREC 0x0008 /* Voice recognition activation */
+#define BTA_AG_PEER_FEAT_VOL 0x0010 /* Remote volume control */
+#define BTA_AG_PEER_FEAT_ECS 0x0020 /* Enhanced Call Status */
+#define BTA_AG_PEER_FEAT_ECC 0x0040 /* Enhanced Call Control */
+#define BTA_AG_PEER_FEAT_CODEC 0x0080 /* Codec Negotiation */
+#define BTA_AG_PEER_FEAT_VOIP 0x0100 /* VoIP call */
+
+typedef UINT16 tBTA_AG_PEER_FEAT;
+
+/* HFP peer supported codec masks */
+#define BTA_AG_CODEC_NONE BTM_SCO_CODEC_NONE
+#define BTA_AG_CODEC_CVSD BTM_SCO_CODEC_CVSD /* CVSD */
+#define BTA_AG_CODEC_MSBC BTM_SCO_CODEC_MSBC /* mSBC */
+typedef UINT16 tBTA_AG_PEER_CODEC;
+
+/* HFP errcode - Set when BTA_AG_OK_ERROR is returned in 'ok_flag' */
+#define BTA_AG_ERR_PHONE_FAILURE 0 /* Phone Failure */
+#define BTA_AG_ERR_NO_CONN_PHONE 1 /* No connection to phone */
+#define BTA_AG_ERR_OP_NOT_ALLOWED 3 /* Operation not allowed */
+#define BTA_AG_ERR_OP_NOT_SUPPORTED 4 /* Operation not supported */
+#define BTA_AG_ERR_PHSIM_PIN_REQ 5 /* PH-SIM PIN required */
+#define BTA_AG_ERR_SIM_NOT_INSERTED 10 /* SIM not inserted */
+#define BTA_AG_ERR_SIM_PIN_REQ 11 /* SIM PIN required */
+#define BTA_AG_ERR_SIM_PUK_REQ 12 /* SIM PUK required */
+#define BTA_AG_ERR_SIM_FAILURE 13 /* SIM failure */
+#define BTA_AG_ERR_SIM_BUSY 14 /* SIM busy */
+#define BTA_AG_ERR_INCORRECT_PWD 16 /* Incorrect password */
+#define BTA_AG_ERR_SIM_PIN2_REQ 17 /* SIM PIN2 required */
+#define BTA_AG_ERR_SIM_PUK2_REQ 18 /* SIM PUK2 required */
+#define BTA_AG_ERR_MEMORY_FULL 20 /* Memory full */
+#define BTA_AG_ERR_INVALID_INDEX 21 /* Invalid index */
+#define BTA_AG_ERR_MEMORY_FAILURE 23 /* Memory failure */
+#define BTA_AG_ERR_TEXT_TOO_LONG 24 /* Text string too long */
+#define BTA_AG_ERR_INV_CHAR_IN_TSTR 25 /* Invalid characters in text string */
+#define BTA_AG_ERR_DSTR_TOO_LONG 26 /* Dial string too long */
+#define BTA_AG_ERR_INV_CHAR_IN_DSTR 27 /* Invalid characters in dial string */
+#define BTA_AG_ERR_NO_NETWORK_SERV 30 /* No network service */
+#define BTA_AG_ERR_NETWORK_TIME_OUT 31 /* Network timeout */
+#define BTA_AG_ERR_NO_NET_EMG_ONLY 32 /* Network not allowed - emergency service only */
+#define BTA_AG_ERR_VOIP_CS_CALLS 33 /* AG cannot create simultaneous VoIP and CS calls */
+#define BTA_AG_ERR_NOT_FOR_VOIP 34 /* Not supported on this call type(VoIP) */
+#define BTA_AG_ERR_SIP_RESP_CODE 35 /* SIP 3 digit response code */
+
+#if 0 /* Not Used in Bluetooth HFP 1.5 Specification */
+#define BTA_AG_ERR_PHADAP_LNK_RES 2 /* Phone-adapter link reserved */
+#define BTA_AG_ERR_PHFSIM_PIN_REQ 6 /* PH-FSIM PIN required */
+#define BTA_AG_ERR_PHFSIM_PUK_REQ 7 /* PH-FSIM PUK required */
+#define BTA_AG_ERR_SIM_WRONG 15 /* SIM wrong */
+#define BTA_AG_ERR_NOT_FOUND 22 /* Not found */
+#define BTA_AG_ERR_NETWORK_TIMEOUT 31 /* Network timeout */
+#define BTA_AG_ERR_NET_PIN_REQ 40 /* Network personalization PIN required */
+#define BTA_AG_ERR_NET_PUK_REQ 41 /* Network personalization PUK required */
+#define BTA_AG_ERR_SUBSET_PIN_REQ 42 /* Network subset personalization PIN required */
+#define BTA_AG_ERR_SUBSET_PUK_REQ 43 /* Network subset personalization PUK required */
+#define BTA_AG_ERR_SERVPRO_PIN_REQ 44 /* Service provider personalization PIN required */
+#define BTA_AG_ERR_SERVPRO_PUK_REQ 45 /* Service provider personalization PUK required */
+#define BTA_AG_ERR_CORP_PIN_REQ 46 /* Corporate personalization PIN required */
+#define BTA_AG_ERR_CORP_PUK_REQ 47 /* Corporate personalization PUK required */
+#define BTA_AG_ERR_UNKNOWN 100 /* Unknown error */
+/* GPRS-related errors */
+#define BTA_AG_ERR_ILL_MS 103 /* Illegal MS (#3) */
+#define BTA_AG_ERR_ILL_ME 106 /* Illegal ME (#6) */
+#define BTA_AG_ERR_GPRS_NOT_ALLOWED 107 /* GPRS services not allowed (#7) */
+#define BTA_AG_ERR_PLMN_NOT_ALLOWED 111 /* PLMN services not allowed (#11) */
+#define BTA_AG_ERR_LOC_NOT_ALLOWED 112 /* Location area not allowed (#12) */
+#define BTA_AG_ERR_ROAM_NOT_ALLOWED 113 /* Roaming not allowed in this location area (#13) */
+/* Errors related to a failure to Activate a Context */
+#define BTA_AG_ERR_OPT_NOT_SUPP 132 /* Service option not supported (#32) */
+#define BTA_AG_ERR_OPT_NOT_SUBSCR 133 /* Requested service option not subscribed (#33) */
+#define BTA_AG_ERR_OPT_OUT_OF_ORDER 134 /* Service option temporarily out of order (#34) */
+#define BTA_AG_ERR_PDP_AUTH_FAILURE 149 /* PDP authentication failure */
+/* Other GPRS errors */
+#define BTA_AG_ERR_INV_MOBILE_CLASS 150 /* Invalid mobile class */
+#define BTA_AG_ERR_UNSPEC_GPRS_ERR 148 /* Unspecified GPRS error */
+#endif /* Unused error codes */
+
+
+/* HFP result data 'ok_flag' */
+#define BTA_AG_OK_CONTINUE 0 /* Send out response (more responses coming) */
+#define BTA_AG_OK_DONE 1 /* Send out response followed by OK (finished) */
+#define BTA_AG_OK_ERROR 2 /* Error response */
+
+/* BTRH values */
+#define BTA_AG_BTRH_SET_HOLD 0 /* Put incoming call on hold */
+#define BTA_AG_BTRH_SET_ACC 1 /* Accept incoming call on hold */
+#define BTA_AG_BTRH_SET_REJ 2 /* Reject incoming call on hold */
+#define BTA_AG_BTRH_READ 3 /* Read the current value */
+#define BTA_AG_BTRH_NO_RESP 4 /* Not in RH States (reply to read) */
+
+/* ASCII character string of arguments to the AT command or result */
+#ifndef BTA_AG_AT_MAX_LEN
+#define BTA_AG_AT_MAX_LEN 256
+#endif
+
+/* data associated with BTA_AG_IND_RES */
+typedef struct
+{
+ UINT16 id;
+ UINT16 value;
+} tBTA_AG_IND;
+
+/* data type for BTA_AgResult() */
+typedef struct
+{
+ char str[BTA_AG_AT_MAX_LEN+1];
+ tBTA_AG_IND ind;
+ UINT16 num;
+ UINT16 audio_handle;
+ UINT16 errcode; /* Valid only if 'ok_flag' is set to BTA_AG_OK_ERROR */
+ UINT8 ok_flag; /* Indicates if response is finished, and if error occurred */
+ BOOLEAN state;
+} tBTA_AG_RES_DATA;
+
+/* AG callback events */
+#define BTA_AG_ENABLE_EVT 0 /* AG enabled */
+#define BTA_AG_REGISTER_EVT 1 /* AG registered */
+#define BTA_AG_OPEN_EVT 2 /* AG connection open */
+#define BTA_AG_CLOSE_EVT 3 /* AG connection closed */
+#define BTA_AG_CONN_EVT 4 /* Service level connection opened */
+#define BTA_AG_AUDIO_OPEN_EVT 5 /* Audio connection open */
+#define BTA_AG_AUDIO_CLOSE_EVT 6 /* Audio connection closed */
+#define BTA_AG_SPK_EVT 7 /* Speaker volume changed */
+#define BTA_AG_MIC_EVT 8 /* Microphone volume changed */
+#define BTA_AG_AT_CKPD_EVT 9 /* CKPD from the HS */
+#define BTA_AG_DISABLE_EVT 30 /* AG disabled */
+
+/* Values below are for HFP only */
+#define BTA_AG_AT_A_EVT 10 /* Answer a call */
+#define BTA_AG_AT_D_EVT 11 /* Place a call using number or memory dial */
+#define BTA_AG_AT_CHLD_EVT 12 /* Call hold */
+#define BTA_AG_AT_CHUP_EVT 13 /* Hang up a call */
+#define BTA_AG_AT_CIND_EVT 14 /* Read indicator settings */
+#define BTA_AG_AT_VTS_EVT 15 /* Transmit DTMF tone */
+#define BTA_AG_AT_BINP_EVT 16 /* Retrieve number from voice tag */
+#define BTA_AG_AT_BLDN_EVT 17 /* Place call to last dialed number */
+#define BTA_AG_AT_BVRA_EVT 18 /* Enable/disable voice recognition */
+#define BTA_AG_AT_NREC_EVT 19 /* Disable echo canceling */
+#define BTA_AG_AT_CNUM_EVT 20 /* Retrieve subscriber number */
+#define BTA_AG_AT_BTRH_EVT 21 /* CCAP-style incoming call hold */
+#define BTA_AG_AT_CLCC_EVT 22 /* Query list of current calls */
+#define BTA_AG_AT_COPS_EVT 23 /* Query list of current calls */
+#define BTA_AG_AT_UNAT_EVT 24 /* Unknown AT command */
+#define BTA_AG_AT_CBC_EVT 25 /* Battery Level report from HF */
+#define BTA_AG_AT_BAC_EVT 26 /* Codec select */
+#define BTA_AG_AT_BCS_EVT 27 /* Codec select */
+
+typedef UINT8 tBTA_AG_EVT;
+
+/* data associated with most non-AT events */
+typedef struct
+{
+ UINT16 handle;
+ UINT8 app_id;
+} tBTA_AG_HDR;
+
+/* data associated with BTA_AG_REGISTER_EVT */
+typedef struct
+{
+ tBTA_AG_HDR hdr;
+ tBTA_AG_STATUS status;
+} tBTA_AG_REGISTER;
+
+/* data associated with BTA_AG_OPEN_EVT */
+typedef struct
+{
+ tBTA_AG_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_SERVICE_ID service_id;
+ tBTA_AG_STATUS status;
+} tBTA_AG_OPEN;
+
+/* data associated with BTA_AG_CONN_EVT */
+typedef struct
+{
+ tBTA_AG_HDR hdr;
+ tBTA_AG_PEER_FEAT peer_feat;
+ tBTA_AG_PEER_CODEC peer_codec;
+} tBTA_AG_CONN;
+
+/* data associated with AT command event */
+typedef struct
+{
+ tBTA_AG_HDR hdr;
+ char str[BTA_AG_AT_MAX_LEN+1];
+ UINT16 num;
+ UINT8 idx; /* call number used by CLCC and CHLD */
+} tBTA_AG_VAL;
+
+/* union of data associated with AG callback */
+typedef union
+{
+ tBTA_AG_HDR hdr;
+ tBTA_AG_REGISTER reg;
+ tBTA_AG_OPEN open;
+ tBTA_AG_CONN conn;
+ tBTA_AG_VAL val;
+} tBTA_AG;
+
+/* AG callback */
+typedef void (tBTA_AG_CBACK)(tBTA_AG_EVT event, tBTA_AG *p_data);
+
+/* indicator constants HFP 1.1 and later */
+#define BTA_AG_IND_CALL 1 /* position of call indicator */
+#define BTA_AG_IND_CALLSETUP 2 /* position of callsetup indicator */
+#define BTA_AG_IND_SERVICE 3 /* position of service indicator */
+
+/* indicator constants HFP 1.5 and later */
+#define BTA_AG_IND_SIGNAL 4 /* position of signal strength indicator */
+#define BTA_AG_IND_ROAM 5 /* position of roaming indicator */
+#define BTA_AG_IND_BATTCHG 6 /* position of battery charge indicator */
+#define BTA_AG_IND_CALLHELD 7 /* position of callheld indicator */
+#define BTA_AG_IND_BEARER 8 /* position of bearer indicator */
+
+/* call indicator values */
+#define BTA_AG_CALL_INACTIVE 0 /* Phone call inactive */
+#define BTA_AG_CALL_ACTIVE 1 /* Phone call active */
+
+/* callsetup indicator values */
+#define BTA_AG_CALLSETUP_NONE 0 /* Not currently in call set up */
+#define BTA_AG_CALLSETUP_INCOMING 1 /* Incoming call process ongoing */
+#define BTA_AG_CALLSETUP_OUTGOING 2 /* Outgoing call set up is ongoing */
+#define BTA_AG_CALLSETUP_ALERTING 3 /* Remote party being alerted in an outgoing call */
+
+/* service indicator values */
+#define BTA_AG_SERVICE_NONE 0 /* Neither CS nor VoIP service is available */
+#define BTA_AG_SERVICE_CS 1 /* Only CS service is available */
+#define BTA_AG_SERVICE_VOIP 2 /* Only VoIP service is available */
+#define BTA_AG_SERVICE_CS_VOIP 3 /* Both CS and VoIP services available */
+
+/* callheld indicator values */
+#define BTA_AG_CALLHELD_INACTIVE 0 /* No held calls */
+#define BTA_AG_CALLHELD_ACTIVE 1 /* Call held and call active */
+#define BTA_AG_CALLHELD_NOACTIVE 2 /* Call held and no call active */
+
+/* signal strength indicator values */
+#define BTA_AG_ROAMING_INACTIVE 0 /* Phone call inactive */
+#define BTA_AG_ROAMING_ACTIVE 1 /* Phone call active */
+
+/* bearer indicator values */
+#define BTA_AG_BEARER_WLAN 0 /* WLAN */
+#define BTA_AG_BEARER_BLUETOOTH 1 /* Bluetooth */
+#define BTA_AG_BEARER_WIRED 2 /* Wired */
+#define BTA_AG_BEARER_2G3G 3 /* 2G 3G */
+#define BTA_AG_BEARER_WIMAX 4 /* WIMAX */
+#define BTA_AG_BEARER_RES1 5 /* Reserved */
+#define BTA_AG_BEARER_RES2 6 /* Reserved */
+#define BTA_AG_BEARER_RES3 7 /* Reserved */
+
+/* AG configuration structure */
+typedef struct
+{
+ char *cind_info;
+ INT32 conn_tout;
+ UINT16 sco_pkt_types;
+ char *chld_val_ecc;
+ char *chld_val;
+} tBTA_AG_CFG;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function BTA_AgEnable
+**
+** Description Enable the audio gateway service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_AG_ENABLE_EVT. This function must
+** be called before other function in the AG API are
+** called.
+**
+** Returns BTA_SUCCESS if OK, BTA_FAILURE otherwise.
+**
+*******************************************************************************/
+BTA_API tBTA_STATUS BTA_AgEnable(tBTA_AG_PARSE_MODE parse_mode, tBTA_AG_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_AgDisable
+**
+** Description Disable the audio gateway service
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_AgRegister
+**
+** Description Register an Audio Gateway service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgRegister(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,
+ tBTA_AG_FEAT features, char *p_service_names[], UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_AgDeregister
+**
+** Description Deregister an audio gateway service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgDeregister(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function BTA_AgOpen
+**
+** Description Opens a connection to a headset or hands-free device.
+** When connection is open callback function is called
+** with a BTA_AG_OPEN_EVT. Only the data connection is
+** opened. The audio connection is not opened.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgOpen(UINT16 handle, BD_ADDR bd_addr, tBTA_SEC sec_mask, tBTA_SERVICE_MASK services);
+
+/*******************************************************************************
+**
+** Function BTA_AgClose
+**
+** Description Close the current connection to a headset or a handsfree
+** Any current audio connection will also be closed
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgClose(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function BTA_AgAudioOpen
+**
+** Description Opens an audio connection to the currently connected
+** headset or hnadsfree
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgAudioOpen(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function BTA_AgAudioClose
+**
+** Description Close the currently active audio connection to a headset
+** or hnadsfree. The data connection remains open
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgAudioClose(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function BTA_AgResult
+**
+** Description Send an AT result code to a headset or hands-free device.
+** This function is only used when the AG parse mode is set
+** to BTA_AG_PARSE.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgResult(UINT16 handle, tBTA_AG_RES result, tBTA_AG_RES_DATA *p_data);
+
+/*******************************************************************************
+**
+** Function BTA_AgSetCodec
+**
+** Description Specify the codec type to be used for the subsequent
+** audio connection.
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AG_API_H */
+
+
diff --git a/bta/include/bta_ag_ci.h b/bta/include/bta_ag_ci.h
new file mode 100644
index 0000000..3bc0e53
--- /dev/null
+++ b/bta/include/bta_ag_ci.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for audio gateway call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_CI_H
+#define BTA_AG_CI_H
+
+#include "bta_ag_api.h"
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ag_ci_rx_write
+**
+** Description This function is called to send data to the AG when the AG
+** is configured for AT command pass-through. The function
+** copies data to an event buffer and sends it.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_ci_rx_write(UINT16 handle, char *p_data, UINT16 len);
+
+/******************************************************************************
+**
+** Function bta_ag_ci_slc_ready
+**
+** Description This function is called to notify AG that SLC is up at
+** the application. This funcion is only used when the app
+** is running in pass-through mode.
+**
+** Returns void
+**
+******************************************************************************/
+BTA_API extern void bta_ag_ci_slc_ready(UINT16 handle);
+
+// btla-specific ++
+/******************************************************************************
+**
+** Function bta_ag_ci_wbs_command
+**
+** Description This function is called to notify AG that a WBS command is
+** received
+**
+** Returns void
+**
+******************************************************************************/
+BTA_API extern void bta_ag_ci_wbs_command (UINT16 handle, char *p_data, UINT16 len);
+// btla-specific --
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AG_CI_H */
+
diff --git a/bta/include/bta_ag_co.h b/bta/include/bta_ag_co.h
new file mode 100644
index 0000000..c6a3392
--- /dev/null
+++ b/bta/include/bta_ag_co.h
@@ -0,0 +1,112 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for audio gateway call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_CO_H
+#define BTA_AG_CO_H
+
+#include "bta_ag_api.h"
+
+/* Definitions for audio state callout function "state" parameter */
+#define BTA_AG_CO_AUD_STATE_OFF 0
+#define BTA_AG_CO_AUD_STATE_OFF_XFER 1 /* Closed pending transfer of audio */
+#define BTA_AG_CO_AUD_STATE_ON 2
+#define BTA_AG_CO_AUD_STATE_SETUP 3
+
+/*******************************************************************************
+**
+** Function bta_ag_co_init
+**
+** Description This callout function is executed by AG when it is
+** started by calling BTA_AgEnable(). This function can be
+** used by the phone to initialize audio paths or for other
+** initialization purposes.
+**
+**
+** Returns Void.
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_init(void);
+
+/*******************************************************************************
+**
+** Function bta_ag_co_audio_state
+**
+** Description This function is called by the AG before the audio connection
+** is brought up, after it comes up, and after it goes down.
+**
+** Parameters handle - handle of the AG instance
+** state - Audio state
+** BTA_AG_CO_AUD_STATE_OFF - Audio has been turned off
+** BTA_AG_CO_AUD_STATE_OFF_XFER - Audio is closed pending transfer
+** BTA_AG_CO_AUD_STATE_ON - Audio has been turned on
+** BTA_AG_CO_AUD_STATE_SETUP - Audio is about to be turned on
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_audio_state(UINT16 handle, UINT8 app_id, UINT8 state);
+
+/*******************************************************************************
+**
+** Function bta_ag_co_data_open
+**
+** Description This function is executed by AG when a service level connection
+** is opened. The phone can use this function to set
+** up data paths or perform any required initialization or
+** set up particular to the connected service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_data_open(UINT16 handle, tBTA_SERVICE_ID service);
+
+/*******************************************************************************
+**
+** Function bta_ag_co_data_close
+**
+** Description This function is called by AG when a service level
+** connection is closed
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_data_close(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function bta_ag_co_tx_write
+**
+** Description This function is called by the AG to send data to the
+** phone when the AG is configured for AT command pass-through.
+** The implementation of this function must copy the data to
+** the phoneÂ’s memory.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_tx_write(UINT16 handle, UINT8 *p_data, UINT16 len);
+
+#endif /* BTA_AG_CO_H */
+
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
new file mode 100644
index 0000000..81dff39
--- /dev/null
+++ b/bta/include/bta_api.h
@@ -0,0 +1,1730 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for BTA, Broadcom's Bluetooth
+ * application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_API_H
+#define BTA_API_H
+
+#include "data_types.h"
+#include "bt_target.h"
+#include "bt_types.h"
+#include "btm_api.h"
+#include "uipc_msg.h"
+
+#if BLE_INCLUDED == TRUE
+#include "btm_ble_api.h"
+#endif
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* Status Return Value */
+#define BTA_SUCCESS 0 /* Successful operation. */
+#define BTA_FAILURE 1 /* Generic failure. */
+#define BTA_PENDING 2 /* API cannot be completed right now */
+#define BTA_BUSY 3
+#define BTA_NO_RESOURCES 4
+#define BTA_WRONG_MODE 5
+
+typedef UINT8 tBTA_STATUS;
+
+/*
+ * Service ID
+ *
+ * NOTES: When you add a new Service ID for BTA AND require to change the value of BTA_MAX_SERVICE_ID,
+ * make sure that the correct security ID of the new service from Security service definitions (btm_api.h)
+ * should be added to bta_service_id_to_btm_srv_id_lkup_tbl table in bta_dm_act.c.
+ */
+
+#define BTA_RES_SERVICE_ID 0 /* Reserved */
+#define BTA_SPP_SERVICE_ID 1 /* Serial port profile. */
+#define BTA_DUN_SERVICE_ID 2 /* Dial-up networking profile. */
+#define BTA_A2DP_SOURCE_SERVICE_ID 3 /* A2DP Source profile. */
+#define BTA_LAP_SERVICE_ID 4 /* LAN access profile. */
+#define BTA_HSP_SERVICE_ID 5 /* Headset profile. */
+#define BTA_HFP_SERVICE_ID 6 /* Hands-free profile. */
+#define BTA_OPP_SERVICE_ID 7 /* Object push */
+#define BTA_FTP_SERVICE_ID 8 /* File transfer */
+#define BTA_CTP_SERVICE_ID 9 /* Cordless Terminal */
+#define BTA_ICP_SERVICE_ID 10 /* Intercom Terminal */
+#define BTA_SYNC_SERVICE_ID 11 /* Synchronization */
+#define BTA_BPP_SERVICE_ID 12 /* Basic printing profile */
+#define BTA_BIP_SERVICE_ID 13 /* Basic Imaging profile */
+#define BTA_PANU_SERVICE_ID 14 /* PAN User */
+#define BTA_NAP_SERVICE_ID 15 /* PAN Network access point */
+#define BTA_GN_SERVICE_ID 16 /* PAN Group Ad-hoc networks */
+#define BTA_SAP_SERVICE_ID 17 /* SIM Access profile */
+#define BTA_A2DP_SERVICE_ID 18 /* A2DP Sink */
+#define BTA_AVRCP_SERVICE_ID 19 /* A/V remote control */
+#define BTA_HID_SERVICE_ID 20 /* HID */
+#define BTA_VDP_SERVICE_ID 21 /* Video distribution */
+#define BTA_PBAP_SERVICE_ID 22 /* PhoneBook Access Server*/
+#define BTA_HSP_HS_SERVICE_ID 23 /* HFP HS role */
+#define BTA_HFP_HS_SERVICE_ID 24 /* HSP HS role */
+#define BTA_MAP_SERVICE_ID 25 /* Message Access Profile */
+#define BTA_MN_SERVICE_ID 26 /* Message Notification Service */
+#define BTA_HDP_SERVICE_ID 27 /* Health Device Profile */
+#define BTA_PCE_SERVICE_ID 28 /* PhoneBook Access Client*/
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+/* BLE profile service ID */
+#define BTA_BLE_SERVICE_ID 29 /* GATT profile */
+
+// btla-specific ++
+#define BTA_USER_SERVICE_ID 30 /* User requested UUID */
+
+#define BTA_MAX_SERVICE_ID 31
+// btla-specific --
+#else
+#define BTA_USER_SERVICE_ID 29 /* User requested UUID */
+#define BTA_MAX_SERVICE_ID 30
+#endif
+/* service IDs (BTM_SEC_SERVICE_FIRST_EMPTY + 1) to (BTM_SEC_MAX_SERVICES - 1)
+ * are used by BTA JV */
+#define BTA_FIRST_JV_SERVICE_ID (BTM_SEC_SERVICE_FIRST_EMPTY + 1)
+#define BTA_LAST_JV_SERVICE_ID (BTM_SEC_MAX_SERVICES - 1)
+
+typedef UINT8 tBTA_SERVICE_ID;
+
+/* Service ID Mask */
+#define BTA_RES_SERVICE_MASK 0x00000001 /* Reserved */
+#define BTA_SPP_SERVICE_MASK 0x00000002 /* Serial port profile. */
+#define BTA_DUN_SERVICE_MASK 0x00000004 /* Dial-up networking profile. */
+#define BTA_FAX_SERVICE_MASK 0x00000008 /* Fax profile. */
+#define BTA_LAP_SERVICE_MASK 0x00000010 /* LAN access profile. */
+#define BTA_HSP_SERVICE_MASK 0x00000020 /* HSP AG role. */
+#define BTA_HFP_SERVICE_MASK 0x00000040 /* HFP AG role */
+#define BTA_OPP_SERVICE_MASK 0x00000080 /* Object push */
+#define BTA_FTP_SERVICE_MASK 0x00000100 /* File transfer */
+#define BTA_CTP_SERVICE_MASK 0x00000200 /* Cordless Terminal */
+#define BTA_ICP_SERVICE_MASK 0x00000400 /* Intercom Terminal */
+#define BTA_SYNC_SERVICE_MASK 0x00000800 /* Synchronization */
+#define BTA_BPP_SERVICE_MASK 0x00001000 /* Print server */
+#define BTA_BIP_SERVICE_MASK 0x00002000 /* Basic Imaging */
+#define BTA_PANU_SERVICE_MASK 0x00004000 /* PAN User */
+#define BTA_NAP_SERVICE_MASK 0x00008000 /* PAN Network access point */
+#define BTA_GN_SERVICE_MASK 0x00010000 /* PAN Group Ad-hoc networks */
+#define BTA_SAP_SERVICE_MASK 0x00020000 /* PAN Group Ad-hoc networks */
+#define BTA_A2DP_SERVICE_MASK 0x00040000 /* Advanced audio distribution */
+#define BTA_AVRCP_SERVICE_MASK 0x00080000 /* A/V remote control */
+#define BTA_HID_SERVICE_MASK 0x00100000 /* HID */
+#define BTA_VDP_SERVICE_MASK 0x00200000 /* Video distribution */
+#define BTA_PBAP_SERVICE_MASK 0x00400000 /* Phone Book Server */
+#define BTA_HSP_HS_SERVICE_MASK 0x00800000 /* HFP HS role */
+#define BTA_HFP_HS_SERVICE_MASK 0x01000000 /* HSP HS role */
+#define BTA_MAS_SERVICE_MASK 0x02000000 /* Message Access Profile */
+#define BTA_MN_SERVICE_MASK 0x04000000 /* Message Notification Profile */
+#define BTA_HL_SERVICE_MASK 0x08000000 /* Health Device Profile */
+#define BTA_PCE_SERVICE_MASK 0x10000000 /* Phone Book Client */
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+#define BTA_BLE_SERVICE_MASK 0x20000000 /* GATT based service */
+// btla-specific ++
+#define BTA_USER_SERVICE_MASK 0x40000000 /* Message Notification Profile */
+// btla-specific --
+#else
+// btla-specific ++
+#define BTA_USER_SERVICE_MASK 0x20000000 /* Message Notification Profile */
+// btla-specific --
+#endif
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+#define BTA_ALL_SERVICE_MASK 0x3FFFFFFF /* All services supported by BTA. */
+#else
+#define BTA_ALL_SERVICE_MASK 0x1FFFFFFF /* All services supported by BTA. */
+#endif
+
+typedef UINT32 tBTA_SERVICE_MASK;
+
+/* extended service mask, including mask with one or more GATT UUID */
+typedef struct
+{
+ tBTA_SERVICE_MASK srvc_mask;
+ UINT8 num_uuid;
+ tBT_UUID *p_uuid;
+}tBTA_SERVICE_MASK_EXT;
+
+/* Security Setting Mask */
+#define BTA_SEC_NONE BTM_SEC_NONE /* No security. */
+#define BTA_SEC_AUTHORIZE (BTM_SEC_IN_AUTHORIZE ) /* Authorization required (only needed for out going connection )*/
+#define BTA_SEC_AUTHENTICATE (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */
+#define BTA_SEC_ENCRYPT (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT) /* Encryption required. */
+
+typedef UINT8 tBTA_SEC;
+
+/* Ignore for Discoverable, Connectable, Pairable and Connectable Paired only device modes */
+
+#define BTA_DM_IGNORE 0xFF
+
+
+/* Discoverable Modes */
+#define BTA_DM_NON_DISC BTM_NON_DISCOVERABLE /* Device is not discoverable. */
+#define BTA_DM_GENERAL_DISC BTM_GENERAL_DISCOVERABLE /* General discoverable. */
+#define BTA_DM_LIMITED_DISC BTM_LIMITED_DISCOVERABLE /* Limited discoverable. */
+
+// btla-specific ++
+typedef UINT16 tBTA_DM_DISC;
+// btla-specific --
+
+/* Connectable Modes */
+#define BTA_DM_NON_CONN BTM_NON_CONNECTABLE /* Device is not connectable. */
+#define BTA_DM_CONN BTM_CONNECTABLE /* Device is connectable. */
+
+// btla-specific ++
+typedef UINT16 tBTA_DM_CONN;
+// btla-specific --
+
+/* Pairable Modes */
+#define BTA_DM_PAIRABLE 1
+#define BTA_DM_NON_PAIRABLE 0
+
+/* Connectable Paired Only Mode */
+#define BTA_DM_CONN_ALL 0
+#define BTA_DM_CONN_PAIRED 1
+
+/* Inquiry Modes */
+#define BTA_DM_GENERAL_INQUIRY BTM_GENERAL_INQUIRY /* Perform general inquiry. */
+#define BTA_DM_LIMITED_INQUIRY BTM_LIMITED_INQUIRY /* Perform limited inquiry. */
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_BLE_INQUIRY_NONE BTM_BLE_INQUIRY_NONE
+#define BTA_BLE_GENERAL_INQUIRY BTM_BLE_GENERAL_INQUIRY /* Perform LE general inquiry. */
+#define BTA_BLE_LIMITED_INQUIRY BTM_BLE_LIMITED_INQUIRY /* Perform LE limited inquiry. */
+#endif
+typedef UINT8 tBTA_DM_INQ_MODE;
+
+/* Inquiry Filter Type */
+#define BTA_DM_INQ_CLR BTM_CLR_INQUIRY_FILTER /* Clear inquiry filter. */
+#define BTA_DM_INQ_DEV_CLASS BTM_FILTER_COND_DEVICE_CLASS /* Filter on device class. */
+#define BTA_DM_INQ_BD_ADDR BTM_FILTER_COND_BD_ADDR /* Filter on a specific BD address. */
+
+typedef UINT8 tBTA_DM_INQ_FILT;
+
+/* Authorize Response */
+#define BTA_DM_AUTH_PERM 0 /* Authorized for future connections to the service */
+#define BTA_DM_AUTH_TEMP 1 /* Authorized for current connection only */
+#define BTA_DM_NOT_AUTH 2 /* Not authorized for the service */
+
+typedef UINT8 tBTA_AUTH_RESP;
+
+/* M/S preferred roles */
+#define BTA_ANY_ROLE 0x00
+#define BTA_MASTER_ROLE_PREF 0x01
+#define BTA_MASTER_ROLE_ONLY 0x02
+
+typedef UINT8 tBTA_PREF_ROLES;
+
+enum
+{
+
+ BTA_DM_NO_SCATTERNET, /* Device doesn't support scatternet, it might
+ support "role switch during connection" for
+ an incoming connection, when it already has
+ another connection in master role */
+ BTA_DM_PARTIAL_SCATTERNET, /* Device supports partial scatternet. It can have
+ simulateous connection in Master and Slave roles
+ for short period of time */
+ BTA_DM_FULL_SCATTERNET /* Device can have simultaneous connection in master
+ and slave roles */
+
+};
+
+
+/* Inquiry filter device class condition */
+typedef struct
+{
+ DEV_CLASS dev_class; /* device class of interest */
+ DEV_CLASS dev_class_mask; /* mask to determine the bits of device class of interest */
+} tBTA_DM_COD_COND;
+
+
+/* Inquiry Filter Condition */
+typedef union
+{
+ BD_ADDR bd_addr; /* BD address of device to filter. */
+ tBTA_DM_COD_COND dev_class_cond; /* Device class filter condition */
+} tBTA_DM_INQ_COND;
+
+/* Inquiry Parameters */
+typedef struct
+{
+ tBTA_DM_INQ_MODE mode; /* Inquiry mode, limited or general. */
+ UINT8 duration; /* Inquiry duration in 1.28 sec units. */
+ UINT8 max_resps; /* Maximum inquiry responses. Set to zero for unlimited responses. */
+ BOOLEAN report_dup; /* report duplicated inquiry response with higher RSSI value */
+ tBTA_DM_INQ_FILT filter_type; /* Filter condition type. */
+ tBTA_DM_INQ_COND filter_cond; /* Filter condition data. */
+} tBTA_DM_INQ;
+
+typedef struct
+{
+ UINT8 bta_dm_eir_min_name_len; /* minimum length of local name when it is shortened */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+ UINT8 bta_dm_eir_uuid16_len; /* length of 16-bit UUIDs */
+ UINT8 *bta_dm_eir_uuid16; /* 16-bit UUIDs */
+#else
+ UINT32 uuid_mask[BTM_EIR_SERVICE_ARRAY_SIZE]; /* mask of UUID list in EIR */
+#endif
+ INT8 *bta_dm_eir_inq_tx_power; /* Inquiry TX power */
+ UINT8 bta_dm_eir_flag_len; /* length of flags in bytes */
+ UINT8 *bta_dm_eir_flags; /* flags for EIR */
+ UINT8 bta_dm_eir_manufac_spec_len; /* length of manufacturer specific in bytes */
+ UINT8 *bta_dm_eir_manufac_spec; /* manufacturer specific */
+} tBTA_DM_EIR_CONF;
+
+#if BLE_INCLUDED == TRUE
+/* ADV data flag bit definition used for BTM_BLE_AD_TYPE_FLAG */
+#define BTA_BLE_LIMIT_DISC_FLAG BTM_BLE_LIMIT_DISC_FLAG
+#define BTA_BLE_GEN_DISC_FLAG BTM_BLE_GEN_DISC_FLAG
+#define BTA_BLE_BREDR_NOT_SPT BTM_BLE_BREDR_NOT_SPT
+#define BTA_BLE_NON_LIMIT_DISC_FLAG BTM_BLE_NON_LIMIT_DISC_FLAG
+#define BTA_BLE_ADV_FLAG_MASK BTM_BLE_ADV_FLAG_MASK
+#define BTA_BLE_LIMIT_DISC_MASK BTM_BLE_LIMIT_DISC_MASK
+
+#define BTA_BLE_AD_BIT_DEV_NAME BTM_BLE_AD_BIT_DEV_NAME
+#define BTA_BLE_AD_BIT_FLAGS BTM_BLE_AD_BIT_FLAGS
+#define BTA_BLE_AD_BIT_MANU BTM_BLE_AD_BIT_MANU
+#define BTA_BLE_AD_BIT_TX_PWR BTM_BLE_AD_BIT_TX_PWR
+#define BTA_BLE_AD_BIT_ATTR BTM_BLE_AD_BIT_ATTR
+#define BTA_BLE_AD_BIT_INT_RANGE BTM_BLE_AD_BIT_INT_RANGE
+#define BTA_BLE_AD_BIT_SERVICE BTM_BLE_AD_BIT_SERVICE
+#define BTA_BLE_AD_BIT_SERVICE_SOL BTM_BLE_AD_BIT_SERVICE_SOL
+#define BTA_BLE_AD_BIT_SERVICE_DATA BTM_BLE_AD_BIT_SERVICE_DATA
+#define BTA_BLE_AD_BIT_SIGN_DATA BTM_BLE_AD_BIT_SIGN_DATA
+typedef UINT16 tBTA_BLE_AD_MASK;
+
+/* slave preferred connection interval range */
+typedef struct
+{
+ UINT16 low;
+ UINT16 hi;
+
+}tBTA_BLE_INT_RANGE;
+
+/* Service tag supported in the device */
+typedef struct
+{
+ UINT8 num_service;
+ BOOLEAN list_cmpl;
+ UINT16 *p_uuid;
+}tBTA_BLE_SERVICE;
+
+/* attribute data */
+typedef struct
+{
+ UINT16 uuid;
+ UINT16 data_len;
+ UINT8 *p_data;
+}tBTA_BLE_ATTR;
+
+#define BTA_BLE_NUM_AD_ATTR_MAX BTM_BLE_NUM_AD_ATTR_MAX
+
+/* attribute list contained in adv data */
+typedef struct
+{
+ UINT8 num_attr;
+ tBTA_BLE_ATTR attr_list[BTA_BLE_NUM_AD_ATTR_MAX];
+}tBTA_BLE_ATTR_DATA;
+
+typedef struct
+{
+ UINT8 len;
+ UINT8 *p_val;
+}tBTA_BLE_MANU;
+
+typedef struct
+{
+ tBTA_BLE_MANU manu; /* manufactuer data */
+ tBTA_BLE_INT_RANGE int_range; /* slave prefered conn interval range */
+ tBTA_BLE_SERVICE services; /* services */
+ tBTA_BLE_ATTR_DATA attr; /* attribute data */
+ UINT8 flag;
+}tBTA_BLE_ADV_DATA;
+
+/* These are the fields returned in each device adv packet. It
+** is returned in the results callback if registered.
+*/
+typedef struct
+{
+ UINT8 conn_mode;
+ tBTA_BLE_AD_MASK ad_mask; /* mask of the valid adv data field */
+ UINT8 flag;
+ UINT8 tx_power_level;
+ UINT8 remote_name_len;
+ UINT8 *p_remote_name;
+ tBTA_BLE_ATTR_DATA attr_data;
+ tBTA_BLE_SERVICE service;
+} tBTA_BLE_INQ_DATA;
+#endif
+
+typedef INT8 tBTA_DM_RSSI_VALUE;
+typedef UINT8 tBTA_DM_LINK_QUALITY_VALUE;
+
+
+/* signal strength mask */
+#define BTA_SIG_STRENGTH_RSSI_MASK 1
+#define BTA_SIG_STRENGTH_LINK_QUALITY_MASK 2
+
+typedef UINT8 tBTA_SIG_STRENGTH_MASK;
+
+
+/* Security Callback Events */
+#define BTA_DM_ENABLE_EVT 0 /* Enable Event */
+#define BTA_DM_DISABLE_EVT 1 /* Disable Event */
+#define BTA_DM_PIN_REQ_EVT 2 /* PIN request. */
+#define BTA_DM_AUTH_CMPL_EVT 3 /* Authentication complete indication. */
+#define BTA_DM_AUTHORIZE_EVT 4 /* Authorization request. */
+#define BTA_DM_LINK_UP_EVT 5 /* Connection UP event */
+#define BTA_DM_LINK_DOWN_EVT 6 /* Connection DOWN event */
+#define BTA_DM_SIG_STRENGTH_EVT 7 /* Signal strength for bluetooth connection */
+#define BTA_DM_BUSY_LEVEL_EVT 8 /* System busy level */
+#define BTA_DM_BOND_CANCEL_CMPL_EVT 9 /* Bond cancel complete indication */
+#define BTA_DM_SP_CFM_REQ_EVT 10 /* Simple Pairing User Confirmation request. */
+#define BTA_DM_SP_KEY_NOTIF_EVT 11 /* Simple Pairing Passkey Notification */
+#define BTA_DM_SP_RMT_OOB_EVT 12 /* Simple Pairing Remote OOB Data request. */
+#define BTA_DM_SP_KEYPRESS_EVT 13 /* Key press notification event. */
+#define BTA_DM_ROLE_CHG_EVT 14 /* Role Change event. */
+#define BTA_DM_BLE_KEY_EVT 15 /* BLE SMP key event for peer device keys */
+#define BTA_DM_BLE_SEC_REQ_EVT 16 /* BLE SMP security request */
+#define BTA_DM_BLE_PASSKEY_NOTIF_EVT 17 /* SMP passkey notification event */
+#define BTA_DM_BLE_PASSKEY_REQ_EVT 18 /* SMP passkey request event */
+#define BTA_DM_BLE_OOB_REQ_EVT 19 /* SMP OOB request event */
+#define BTA_DM_BLE_LOCAL_IR_EVT 20 /* BLE local IR event */
+#define BTA_DM_BLE_LOCAL_ER_EVT 21 /* BLE local ER event */
+// btla-specific ++
+#define BTA_DM_BLE_AUTH_CMPL_EVT 22 /* BLE Auth complete */
+// btla-specific --
+#define BTA_DM_DEV_UNPAIRED_EVT 23
+#define BTA_DM_HW_ERROR_EVT 24 /* BT Chip H/W error */
+typedef UINT8 tBTA_DM_SEC_EVT;
+
+/* Structure associated with BTA_DM_ENABLE_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address of local device. */
+ tBTA_STATUS status;
+} tBTA_DM_ENABLE;
+
+/* Structure associated with BTA_DM_PIN_REQ_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ BD_NAME bd_name; /* Name of peer device. */
+ DEV_CLASS dev_class; /* Class of Device */
+} tBTA_DM_PIN_REQ;
+
+/* BLE related definition */
+
+#define BTA_DM_AUTH_FAIL_BASE (HCI_ERR_MAX_ERR + 10)
+#define BTA_DM_AUTH_CONVERT_SMP_CODE(x) (BTA_DM_AUTH_FAIL_BASE + (x))
+#define BTA_DM_AUTH_SMP_PASSKEY_FAIL BTA_DM_AUTH_CONVERT_SMP_CODE (SMP_PASSKEY_ENTRY_FAIL)
+#define BTA_DM_AUTH_SMP_OOB_FAIL (BTA_DM_AUTH_FAIL_BASE + SMP_OOB_FAIL)
+#define BTA_DM_AUTH_SMP_PAIR_AUTH_FAIL (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_AUTH_FAIL)
+#define BTA_DM_AUTH_SMP_CONFIRM_VALUE_FAIL (BTA_DM_AUTH_FAIL_BASE + SMP_CONFIRM_VALUE_ERR)
+#define BTA_DM_AUTH_SMP_PAIR_NOT_SUPPORT (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_NOT_SUPPORT)
+#define BTA_DM_AUTH_SMP_ENC_KEY_SIZE (BTA_DM_AUTH_FAIL_BASE + SMP_ENC_KEY_SIZE)
+#define BTA_DM_AUTH_SMP_INVALID_CMD (BTA_DM_AUTH_FAIL_BASE + SMP_INVALID_CMD)
+#define BTA_DM_AUTH_SMP_UNKNOWN_ERR (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_FAIL_UNKNOWN)
+#define BTA_DM_AUTH_SMP_REPEATED_ATTEMPT (BTA_DM_AUTH_FAIL_BASE + SMP_REPEATED_ATTEMPTS)
+#define BTA_DM_AUTH_SMP_INTERNAL_ERR (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_INTERNAL_ERR)
+#define BTA_DM_AUTH_SMP_UNKNOWN_IO (BTA_DM_AUTH_FAIL_BASE + SMP_UNKNOWN_IO_CAP)
+#define BTA_DM_AUTH_SMP_INIT_FAIL (BTA_DM_AUTH_FAIL_BASE + SMP_INIT_FAIL)
+#define BTA_DM_AUTH_SMP_CONFIRM_FAIL (BTA_DM_AUTH_FAIL_BASE + SMP_CONFIRM_FAIL)
+#define BTA_DM_AUTH_SMP_BUSY (BTA_DM_AUTH_FAIL_BASE + SMP_BUSY)
+#define BTA_DM_AUTH_SMP_ENC_FAIL (BTA_DM_AUTH_FAIL_BASE + SMP_ENC_FAIL)
+#define BTA_DM_AUTH_SMP_RSP_TIMEOUT (BTA_DM_AUTH_FAIL_BASE + SMP_RSP_TIMEOUT)
+
+/* connection parameter boundary value and dummy value */
+#define BTA_DM_BLE_SCAN_INT_MIN BTM_BLE_SCAN_INT_MIN
+#define BTA_DM_BLE_SCAN_INT_MAX BTM_BLE_SCAN_INT_MAX
+#define BTA_DM_BLE_SCAN_WIN_MIN BTM_BLE_SCAN_WIN_MIN
+#define BTA_DM_BLE_SCAN_WIN_MAX BTM_BLE_SCAN_WIN_MAX
+#define BTA_DM_BLE_CONN_INT_MIN BTM_BLE_CONN_INT_MIN
+#define BTA_DM_BLE_CONN_INT_MAX BTM_BLE_CONN_INT_MAX
+#define BTA_DM_BLE_CONN_LATENCY_MAX BTM_BLE_CONN_LATENCY_MAX
+#define BTA_DM_BLE_CONN_SUP_TOUT_MIN BTM_BLE_CONN_SUP_TOUT_MIN
+#define BTA_DM_BLE_CONN_SUP_TOUT_MAX BTM_BLE_CONN_SUP_TOUT_MAX
+#define BTA_DM_BLE_CONN_PARAM_UNDEF BTM_BLE_CONN_PARAM_UNDEF /* use this value when a specific value not to be overwritten */
+
+
+#define BTA_LE_KEY_PENC BTM_LE_KEY_PENC /* encryption information of peer device */
+#define BTA_LE_KEY_PID BTM_LE_KEY_PID /* identity key of the peer device */
+#define BTA_LE_KEY_PCSRK BTM_LE_KEY_PCSRK /* peer SRK */
+#define BTA_LE_KEY_LENC BTM_LE_KEY_LENC /* master role security information:div */
+#define BTA_LE_KEY_LID BTM_LE_KEY_LID /* master device ID key */
+#define BTA_LE_KEY_LCSRK BTM_LE_KEY_LCSRK /* local CSRK has been deliver to peer */
+typedef UINT8 tBTA_LE_KEY_TYPE; /* can be used as a bit mask */
+
+
+typedef tBTM_LE_PENC_KEYS tBTA_LE_PENC_KEYS ;
+typedef tBTM_LE_PCSRK_KEYS tBTA_LE_PCSRK_KEYS;
+typedef tBTM_LE_LENC_KEYS tBTA_LE_LENC_KEYS ;
+typedef tBTM_LE_LCSRK_KEYS tBTA_LE_LCSRK_KEYS ;
+
+typedef union
+{
+ tBTA_LE_PENC_KEYS penc_key; /* received peer encryption key */
+ tBTA_LE_PCSRK_KEYS psrk_key; /* received peer device SRK */
+ BT_OCTET16 pid_key; /* peer device ID key */
+ tBTA_LE_LENC_KEYS lenc_key; /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
+ tBTA_LE_LCSRK_KEYS lcsrk_key; /* local device CSRK = d1(ER,DIV,1)*/
+}tBTA_LE_KEY_VALUE;
+
+#define BTA_BLE_LOCAL_KEY_TYPE_ID 1
+#define BTA_BLE_LOCAL_KEY_TYPE_ER 2
+typedef UINT8 tBTA_DM_BLE_LOCAL_KEY_MASK;
+
+typedef struct
+{
+ BT_OCTET16 ir;
+ BT_OCTET16 irk;
+ BT_OCTET16 dhk;
+}tBTA_BLE_LOCAL_ID_KEYS;
+
+#define BTA_DM_SEC_GRANTED BTA_SUCCESS
+#define BTA_DM_SEC_PAIR_NOT_SPT BTA_DM_AUTH_SMP_PAIR_NOT_SUPPORT
+#define BTA_DM_SEC_REP_ATTEMPTS BTA_DM_AUTH_SMP_REPEATED_ATTEMPT
+typedef UINT8 tBTA_DM_BLE_SEC_GRANT;
+
+
+#define BTA_DM_BLE_ONN_NONE BTM_BLE_CONN_NONE
+#define BTA_DM_BLE_CONN_AUTO BTM_BLE_CONN_AUTO
+#define BTA_DM_BLE_CONN_SELECTIVE BTM_BLE_CONN_SELECTIVE
+typedef UINT8 tBTA_DM_BLE_CONN_TYPE;
+
+typedef BOOLEAN (tBTA_DM_BLE_SEL_CBACK)(BD_ADDR random_bda, UINT8 *p_remote_name);
+
+/* Structure associated with BTA_DM_BLE_SEC_REQ_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* peer address */
+ BD_NAME bd_name; /* peer device name */
+} tBTA_DM_BLE_SEC_REQ;
+
+typedef struct
+{
+ BD_ADDR bd_addr; /* peer address */
+ tBTM_LE_KEY_TYPE key_type;
+ tBTM_LE_KEY_VALUE key_value;
+}tBTA_DM_BLE_KEY;
+
+/* Structure associated with BTA_DM_AUTH_CMPL_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ BD_NAME bd_name; /* Name of peer device. */
+ BOOLEAN key_present; /* Valid link key value in key element */
+ LINK_KEY key; /* Link key associated with peer device. */
+ UINT8 key_type; /* The type of Link Key */
+ BOOLEAN success; /* TRUE of authentication succeeded, FALSE if failed. */
+ UINT8 fail_reason; /* The HCI reason/error code for when success=FALSE */
+
+} tBTA_DM_AUTH_CMPL;
+
+
+/* Structure associated with BTA_DM_AUTHORIZE_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ BD_NAME bd_name; /* Name of peer device. */
+ tBTA_SERVICE_ID service; /* Service ID to authorize. */
+// btla-specific ++
+ DEV_CLASS dev_class;
+// btla-specific --
+} tBTA_DM_AUTHORIZE;
+
+/* Structure associated with BTA_DM_LINK_UP_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+} tBTA_DM_LINK_UP;
+
+/* Structure associated with BTA_DM_LINK_DOWN_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ UINT8 status; /* connection open/closed */
+} tBTA_DM_LINK_DOWN;
+
+/* Structure associated with BTA_DM_ROLE_CHG_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ UINT8 new_role; /* the new connection role */
+} tBTA_DM_ROLE_CHG;
+
+/* Structure associated with BTA_DM_SIG_STRENGTH_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ tBTA_SIG_STRENGTH_MASK mask; /* mask for the values that are valid */
+ tBTA_DM_RSSI_VALUE rssi_value;
+ tBTA_DM_LINK_QUALITY_VALUE link_quality_value;
+
+} tBTA_DM_SIG_STRENGTH;
+
+/* Structure associated with BTA_DM_BUSY_LEVEL_EVT */
+typedef struct
+{
+ UINT8 level; /* when paging or inquiring, level is 10.
+ Otherwise, the number of ACL links */
+} tBTA_DM_BUSY_LEVEL;
+
+#define BTA_IO_CAP_OUT BTM_IO_CAP_OUT /* DisplayOnly */
+#define BTA_IO_CAP_IO BTM_IO_CAP_IO /* DisplayYesNo */
+#define BTA_IO_CAP_IN BTM_IO_CAP_IN /* KeyboardOnly */
+#define BTA_IO_CAP_NONE BTM_IO_CAP_NONE /* NoInputNoOutput */
+typedef tBTM_IO_CAP tBTA_IO_CAP;
+
+#define BTA_AUTH_SP_NO BTM_AUTH_SP_NO /* 0 MITM Protection Not Required - Single Profile/non-bonding
+ Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_SP_YES BTM_AUTH_SP_YES /* 1 MITM Protection Required - Single Profile/non-bonding
+ Use IO Capabilities to determine authentication procedure */
+#define BTA_AUTH_AP_NO BTM_AUTH_AP_NO /* 2 MITM Protection Not Required - All Profiles/dedicated bonding
+ Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_AP_YES BTM_AUTH_AP_YES /* 3 MITM Protection Required - All Profiles/dedicated bonding
+ Use IO Capabilities to determine authentication procedure */
+#define BTA_AUTH_SPGB_NO BTM_AUTH_SPGB_NO /* 4 MITM Protection Not Required - Single Profiles/general bonding
+ Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_SPGB_YES BTM_AUTH_SPGB_YES /* 5 MITM Protection Required - Single Profiles/general bonding
+ Use IO Capabilities to determine authentication procedure */
+typedef tBTM_AUTH_REQ tBTA_AUTH_REQ;
+
+#define BTA_AUTH_DD_BOND BTM_AUTH_DD_BOND /* 2 this bit is set for dedicated bonding */
+#define BTA_AUTH_GEN_BOND BTM_AUTH_SPGB_NO /* 4 this bit is set for general bonding */
+#define BTA_AUTH_BONDS BTM_AUTH_BONDS /* 6 the general/dedicated bonding bits */
+
+#define BTA_LE_AUTH_NO_BOND BTM_LE_AUTH_REQ_NO_BOND /* 0*/
+#define BTA_LE_AUTH_BOND BTM_LE_AUTH_REQ_BOND /* 1 << 0 */
+#define BTA_LE_AUTH_REQ_MITM BTM_LE_AUTH_REQ_MITM /* 1 << 2 */
+typedef tBTM_LE_AUTH_REQ tBTA_LE_AUTH_REQ; /* combination of the above bit pattern */
+
+#define BTA_OOB_NONE BTM_OOB_NONE
+#define BTA_OOB_PRESENT BTM_OOB_PRESENT
+#if BTM_OOB_INCLUDED == TRUE
+#define BTA_OOB_UNKNOWN BTM_OOB_UNKNOWN
+#endif
+typedef tBTM_OOB_DATA tBTA_OOB_DATA;
+
+/* Structure associated with BTA_DM_SP_CFM_REQ_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* peer address */
+ DEV_CLASS dev_class; /* peer CoD */
+ BD_NAME bd_name; /* peer device name */
+ UINT32 num_val; /* the numeric value for comparison. If just_works, do not show this number to UI */
+ BOOLEAN just_works; /* TRUE, if "Just Works" association model */
+ tBTA_AUTH_REQ loc_auth_req; /* Authentication required for local device */
+ tBTA_AUTH_REQ rmt_auth_req; /* Authentication required for peer device */
+ tBTA_IO_CAP loc_io_caps; /* IO Capabilities of local device */
+ tBTA_AUTH_REQ rmt_io_caps; /* IO Capabilities of remote device */
+} tBTA_DM_SP_CFM_REQ;
+
+enum
+{
+ BTA_SP_KEY_STARTED, /* passkey entry started */
+ BTA_SP_KEY_ENTERED, /* passkey digit entered */
+ BTA_SP_KEY_ERASED, /* passkey digit erased */
+ BTA_SP_KEY_CLEARED, /* passkey cleared */
+ BTA_SP_KEY_COMPLT /* passkey entry completed */
+};
+typedef UINT8 tBTA_SP_KEY_TYPE;
+
+/* Structure associated with BTA_DM_SP_KEYPRESS_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* peer address */
+ tBTA_SP_KEY_TYPE notif_type;
+}tBTA_DM_SP_KEY_PRESS;
+
+/* Structure associated with BTA_DM_SP_KEY_NOTIF_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* peer address */
+ DEV_CLASS dev_class; /* peer CoD */
+ BD_NAME bd_name; /* peer device name */
+ UINT32 passkey; /* the numeric value for comparison. If just_works, do not show this number to UI */
+} tBTA_DM_SP_KEY_NOTIF;
+
+/* Structure associated with BTA_DM_SP_RMT_OOB_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* peer address */
+ DEV_CLASS dev_class; /* peer CoD */
+ BD_NAME bd_name; /* peer device name */
+} tBTA_DM_SP_RMT_OOB;
+
+/* Structure associated with BTA_DM_BOND_CANCEL_CMPL_EVT */
+typedef struct
+{
+ tBTA_STATUS result; /* TRUE of bond cancel succeeded, FALSE if failed. */
+} tBTA_DM_BOND_CANCEL_CMPL;
+
+/* Union of all security callback structures */
+typedef union
+{
+ tBTA_DM_ENABLE enable; /* BTA enabled */
+ tBTA_DM_PIN_REQ pin_req; /* PIN request. */
+ tBTA_DM_AUTH_CMPL auth_cmpl; /* Authentication complete indication. */
+ tBTA_DM_AUTHORIZE authorize; /* Authorization request. */
+ tBTA_DM_LINK_UP link_up; /* ACL connection down event */
+ tBTA_DM_LINK_DOWN link_down; /* ACL connection down event */
+ tBTA_DM_SIG_STRENGTH sig_strength; /* rssi and link quality value */
+ tBTA_DM_BUSY_LEVEL busy_level; /* System busy level */
+ tBTA_DM_SP_CFM_REQ cfm_req; /* user confirm request */
+ tBTA_DM_SP_KEY_NOTIF key_notif; /* passkey notification */
+ tBTA_DM_SP_RMT_OOB rmt_oob; /* remote oob */
+ tBTA_DM_BOND_CANCEL_CMPL bond_cancel_cmpl; /* Bond Cancel Complete indication */
+ tBTA_DM_SP_KEY_PRESS key_press; /* key press notification event */
+ tBTA_DM_ROLE_CHG role_chg; /* role change event */
+ tBTA_DM_BLE_SEC_REQ ble_req; /* BLE SMP related request */
+ tBTA_DM_BLE_KEY ble_key; /* BLE SMP keys used when pairing */
+ tBTA_BLE_LOCAL_ID_KEYS ble_id_keys; /* IR event */
+ BT_OCTET16 ble_er; /* ER event data */
+} tBTA_DM_SEC;
+
+/* Security callback */
+typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data);
+
+/* Vendor Specific Command Callback */
+typedef tBTM_VSC_CMPL_CB tBTA_VENDOR_CMPL_CBACK;
+
+/* Search callback events */
+#define BTA_DM_INQ_RES_EVT 0 /* Inquiry result for a peer device. */
+#define BTA_DM_INQ_CMPL_EVT 1 /* Inquiry complete. */
+#define BTA_DM_DISC_RES_EVT 2 /* Discovery result for a peer device. */
+#define BTA_DM_DISC_BLE_RES_EVT 3 /* Discovery result for BLE GATT based servoce on a peer device. */
+#define BTA_DM_DISC_CMPL_EVT 4 /* Discovery complete. */
+#define BTA_DM_DI_DISC_CMPL_EVT 5 /* Discovery complete. */
+#define BTA_DM_SEARCH_CANCEL_CMPL_EVT 6 /* Search cancelled */
+
+typedef UINT8 tBTA_DM_SEARCH_EVT;
+
+#define BTA_DM_INQ_RES_IGNORE_RSSI BTM_INQ_RES_IGNORE_RSSI /* 0x7f RSSI value not supplied (ignore it) */
+
+/* Structure associated with BTA_DM_INQ_RES_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ DEV_CLASS dev_class; /* Device class of peer device. */
+ BOOLEAN remt_name_not_required; /* Application sets this flag if it already knows the name of the device */
+ /* If the device name is known to application BTA skips the remote name request */
+ BOOLEAN is_limited; /* TRUE, if the limited inquiry bit is set in the CoD */
+ INT8 rssi; /* The rssi value */
+ UINT8 *p_eir; /* received EIR */
+#if (BLE_INCLUDED == TRUE)
+ UINT8 inq_result_type;
+ UINT8 ble_addr_type;
+ tBTM_BLE_EVT_TYPE ble_evt_type;
+ tBT_DEVICE_TYPE device_type;
+#endif
+
+} tBTA_DM_INQ_RES;
+
+/* Structure associated with BTA_DM_INQ_CMPL_EVT */
+typedef struct
+{
+ UINT8 num_resps; /* Number of inquiry responses. */
+} tBTA_DM_INQ_CMPL;
+
+/* Structure associated with BTA_DM_DI_DISC_CMPL_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ UINT8 num_record; /* Number of DI record */
+ tBTA_STATUS result;
+} tBTA_DM_DI_DISC_CMPL;
+
+/* Structure associated with BTA_DM_DISC_RES_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ BD_NAME bd_name; /* Name of peer device. */
+ tBTA_SERVICE_MASK services; /* Services found on peer device. */
+// btla-specific ++
+ UINT8 * p_raw_data; /* Raw data for discovery DB */
+ UINT32 raw_data_size; /* size of raw data */
+ tBT_DEVICE_TYPE device_type; /* device type in case it is BLE device */
+ UINT32 num_uuids;
+ UINT8 *p_uuid_list;
+// btla-specific --
+ tBTA_STATUS result;
+} tBTA_DM_DISC_RES;
+
+/* Structure associated with tBTA_DM_DISC_BLE_RES */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address peer device. */
+ BD_NAME bd_name; /* Name of peer device. */
+ tBT_UUID service; /* GATT based Services UUID found on peer device. */
+} tBTA_DM_DISC_BLE_RES;
+
+
+/* Union of all search callback structures */
+typedef union
+{
+ tBTA_DM_INQ_RES inq_res; /* Inquiry result for a peer device. */
+ tBTA_DM_INQ_CMPL inq_cmpl; /* Inquiry complete. */
+ tBTA_DM_DISC_RES disc_res; /* Discovery result for a peer device. */
+ tBTA_DM_DISC_BLE_RES disc_ble_res; /* discovery result for GATT based service */
+ tBTA_DM_DI_DISC_CMPL di_disc; /* DI discovery result for a peer device */
+
+} tBTA_DM_SEARCH;
+
+/* Search callback */
+typedef void (tBTA_DM_SEARCH_CBACK)(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data);
+
+/* Execute call back */
+typedef void (tBTA_DM_EXEC_CBACK) (void * p_param);
+
+/* Encryption callback*/
+typedef void (tBTA_DM_ENCRYPT_CBACK) (BD_ADDR bd_addr, tBTA_STATUS result);
+
+#if BLE_INCLUDED == TRUE
+#define BTA_DM_BLE_SEC_NONE BTM_BLE_SEC_NONE
+#define BTA_DM_BLE_SEC_ENCRYPT BTM_BLE_SEC_ENCRYPT
+#define BTA_DM_BLE_SEC_NO_MITM BTM_BLE_SEC_ENCRYPT_NO_MITM
+#define BTA_DM_BLE_SEC_MITM BTM_BLE_SEC_ENCRYPT_MITM
+typedef tBTM_BLE_SEC_ACT tBTA_DM_BLE_SEC_ACT;
+#else
+typedef UINT8 tBTA_DM_BLE_SEC_ACT;
+#endif
+
+/* Maximum service name length */
+#define BTA_SERVICE_NAME_LEN 35
+#define BTA_SERVICE_DESP_LEN BTA_SERVICE_NAME_LEN
+#define BTA_PROVIDER_NAME_LEN BTA_SERVICE_NAME_LEN
+
+
+/* link policy masks */
+#define BTA_DM_LP_SWITCH HCI_ENABLE_MASTER_SLAVE_SWITCH
+#define BTA_DM_LP_HOLD HCI_ENABLE_HOLD_MODE
+#define BTA_DM_LP_SNIFF HCI_ENABLE_SNIFF_MODE
+#define BTA_DM_LP_PARK HCI_ENABLE_PARK_MODE
+typedef UINT16 tBTA_DM_LP_MASK;
+
+/* power mode actions */
+#define BTA_DM_PM_NO_ACTION 0x00 /* no change to the current pm setting */
+#define BTA_DM_PM_PARK 0x10 /* prefers park mode */
+#define BTA_DM_PM_SNIFF 0x20 /* prefers sniff mode */
+#define BTA_DM_PM_SNIFF1 0x21 /* prefers sniff1 mode */
+#define BTA_DM_PM_SNIFF2 0x22 /* prefers sniff2 mode */
+#define BTA_DM_PM_SNIFF3 0x23 /* prefers sniff3 mode */
+#define BTA_DM_PM_SNIFF4 0x24 /* prefers sniff4 mode */
+#define BTA_DM_PM_SNIFF5 0x25 /* prefers sniff5 mode */
+#define BTA_DM_PM_SNIFF6 0x26 /* prefers sniff6 mode */
+#define BTA_DM_PM_SNIFF7 0x27 /* prefers sniff7 mode */
+#define BTA_DM_PM_SNIFF_USER0 0x28 /* prefers user-defined sniff0 mode (testtool only) */
+#define BTA_DM_PM_SNIFF_USER1 0x29 /* prefers user-defined sniff1 mode (testtool only) */
+#define BTA_DM_PM_ACTIVE 0x40 /* prefers active mode */
+#define BTA_DM_PM_RETRY 0x80 /* retry power mode based on current settings */
+#define BTA_DM_PM_NO_PREF 0x01 /* service has no prefernce on power mode setting. eg. connection to service got closed */
+
+typedef UINT8 tBTA_DM_PM_ACTTION;
+
+/* index to bta_dm_ssr_spec */
+#define BTA_DM_PM_SSR0 0
+#define BTA_DM_PM_SSR1 1
+#define BTA_DM_PM_SSR2 2
+#define BTA_DM_PM_SSR3 3
+#define BTA_DM_PM_SSR4 4
+#define BTA_DM_PM_SSR5 5
+#define BTA_DM_PM_SSR6 6
+
+#define BTA_DM_PM_NUM_EVTS 9
+
+#ifndef BTA_DM_PM_PARK_IDX
+#define BTA_DM_PM_PARK_IDX 5 /* the actual index to bta_dm_pm_md[] for PARK mode */
+#endif
+
+#define BTA_DM_SW_BB_TO_MM BTM_SW_BB_TO_MM
+#define BTA_DM_SW_MM_TO_BB BTM_SW_MM_TO_BB
+#define BTA_DM_SW_BB_TO_BTC BTM_SW_BB_TO_BTC
+#define BTA_DM_SW_BTC_TO_BB BTM_SW_BTC_TO_BB
+
+typedef tBTM_SW_DIR tBTA_DM_SW_DIR;
+
+/* Switch callback events */
+#define BTA_DM_SWITCH_CMPL_EVT 0 /* Completion of the Switch API */
+
+typedef UINT8 tBTA_DM_SWITCH_EVT;
+typedef void (tBTA_DM_SWITCH_CBACK)(tBTA_DM_SWITCH_EVT event, tBTA_STATUS status);
+
+/* Audio routing out configuration */
+#define BTA_DM_ROUTE_NONE 0x00 /* No Audio output */
+#define BTA_DM_ROUTE_DAC 0x01 /* routing over analog output */
+#define BTA_DM_ROUTE_I2S 0x02 /* routing over digital (I2S) output */
+#define BTA_DM_ROUTE_BT_MONO 0x04 /* routing over SCO */
+#define BTA_DM_ROUTE_BT_STEREO 0x08 /* routing over BT Stereo */
+#define BTA_DM_ROUTE_HOST 0x10 /* routing over Host */
+#define BTA_DM_ROUTE_FMTX 0x20 /* routing over FMTX */
+#define BTA_DM_ROUTE_FMRX 0x40 /* routing over FMRX */
+#define BTA_DM_ROUTE_BTSNK 0x80 /* routing over BT SNK */
+
+typedef UINT8 tBTA_DM_ROUTE_PATH;
+
+
+/* Device Identification (DI) data structure
+*/
+/* Used to set the DI record */
+typedef tSDP_DI_RECORD tBTA_DI_RECORD;
+/* Used to get the DI record */
+typedef tSDP_DI_GET_RECORD tBTA_DI_GET_RECORD;
+/* SDP discovery database */
+typedef tSDP_DISCOVERY_DB tBTA_DISCOVERY_DB;
+
+#ifndef BTA_DI_NUM_MAX
+#define BTA_DI_NUM_MAX 3
+#endif
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function BTA_EnableBluetooth
+**
+** Description This function initializes BTA and prepares BTA and the
+** Bluetooth protocol stack for use. This function is
+** typically called at startup or when Bluetooth services
+** are required by the phone. This function must be called
+** before calling any other API function.
+**
+**
+** Returns BTA_SUCCESS if successful.
+** BTA_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_DisableBluetooth
+**
+** Description This function disables BTA and the Bluetooth protocol
+** stack. It is called when BTA is no longer being used
+** by any application in the system.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DisableBluetooth(void);
+
+/*******************************************************************************
+**
+** Function BTA_EnableTestMode
+**
+** Description Enables bluetooth device under test mode
+**
+**
+** Returns tBTA_STATUS
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_EnableTestMode(void);
+
+/*******************************************************************************
+**
+** Function BTA_DisableTestMode
+**
+** Description Disable bluetooth device under test mode
+**
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DisableTestMode(void);
+
+/*******************************************************************************
+**
+** Function BTA_DmIsDeviceUp
+**
+** Description This function tests whether the Bluetooth module is up
+** and ready. This is a direct execution function that
+** may lock task scheduling on some platforms.
+**
+**
+** Returns TRUE if the module is ready.
+** FALSE if the module is not ready.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_DmIsDeviceUp(void);
+
+/*******************************************************************************
+**
+** Function BTA_DmSetDeviceName
+**
+** Description This function sets the Bluetooth name of the local device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetDeviceName(char *p_name);
+
+/*******************************************************************************
+**
+** Function BTA_DmSetVisibility
+**
+** Description This function sets the Bluetooth connectable,discoverable,
+** pairable and conn paired only modesmodes of the local device.
+** This controls whether other Bluetooth devices can find and connect to
+** the local device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode, UINT8 pairable_mode, UINT8 conn_filter);
+
+/*******************************************************************************
+**
+** Function BTA_DmSetScanParam
+**
+** Description This function sets the parameters for page scan and
+** inquiry scan.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetScanParam (UINT16 page_scan_interval, UINT16 page_scan_window,
+ UINT16 inquiry_scan_interval, UINT16 inquiry_scan_window);
+
+/*******************************************************************************
+**
+** Function BTA_DmSetAfhChannels
+**
+** Description This function sets the AFH first and
+** last disable channel, so channels within
+** that range are disabled.
+** In order to use this API, BTM_BYPASS_AMP_AUTO_AFH must be set
+** to be TRUE
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetAfhChannels(UINT8 first, UINT8 last);
+
+
+/*******************************************************************************
+**
+** Function BTA_DmVendorSpecificCommand
+**
+** Description This function sends the vendor specific command
+** to the controller
+**
+**
+** Returns tBTA_STATUS
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmVendorSpecificCommand (UINT16 opcode, UINT8 param_len,UINT8 *p_param_buf, tBTA_VENDOR_CMPL_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
+** Function BTA_DmSearch
+**
+** Description This function searches for peer Bluetooth devices. It
+** first performs an inquiry; for each device found from the
+** inquiry it gets the remote name of the device. If
+** parameter services is nonzero, service discovery will be
+** performed on each device for the services specified.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services,
+ tBTA_DM_SEARCH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_DmSearchCancel
+**
+** Description This function cancels a search that has been initiated
+** by calling BTA_DmSearch().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSearchCancel(void);
+
+/*******************************************************************************
+**
+** Function BTA_DmDiscover
+**
+** Description This function performs service discovery for the services
+** of a particular peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiscover(BD_ADDR bd_addr, tBTA_SERVICE_MASK services,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+// btla-specific ++
+/*******************************************************************************
+**
+** Function BTA_DmDiscoverUUID
+**
+** Description This function performs service discovery for the services
+** of a particular peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiscoverUUID(BD_ADDR bd_addr, tSDP_UUID *uuid,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+/*******************************************************************************
+**
+** Function BTA_DmGetCachedRemoteName
+**
+** Description Retieve cached remote name if available
+**
+** Returns BTA_SUCCESS if cached name was retrieved
+** BTA_FAILURE if cached name is not available
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmGetCachedRemoteName(BD_ADDR remote_device, UINT8 **pp_cached_name);
+// btla-specific --
+
+/*******************************************************************************
+**
+** Function BTA_DmIsMaster
+**
+** Description This function checks if the local device is the master of
+** the link to the given device
+**
+** Returns TRUE if master.
+** FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_DmIsMaster(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_DmBond
+**
+** Description This function initiates a bonding procedure with a peer
+** device. The bonding procedure enables authentication
+** and optionally encryption on the Bluetooth link.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBond(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_DmBondCancel
+**
+** Description This function cancels a bonding procedure with a peer
+** device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBondCancel(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_DmPinReply
+**
+** Description This function provides a PIN when one is requested by DM
+** during a bonding procedure. The application should call
+** this function after the security callback is called with
+** a BTA_DM_PIN_REQ_EVT.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmPinReply(BD_ADDR bd_addr, BOOLEAN accept, UINT8 pin_len,
+ UINT8 *p_pin);
+
+/*******************************************************************************
+**
+** Function BTA_DmLinkPolicy
+**
+** Description This function sets/clears the link policy mask to the given
+** bd_addr.
+** If clearing the sniff or park mode mask, the link is put
+** in active mode.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmLinkPolicy(BD_ADDR bd_addr, tBTA_DM_LP_MASK policy_mask,
+ BOOLEAN set);
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function BTA_DmLocalOob
+**
+** Description This function retrieves the OOB data from local controller.
+** The result is reported by bta_dm_co_loc_oob().
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmLocalOob(void);
+#endif /* BTM_OOB_INCLUDED */
+
+/*******************************************************************************
+**
+** Function BTA_DmConfirm
+**
+** Description This function accepts or rejects the numerical value of the
+** Simple Pairing process on BTA_DM_SP_CFM_REQ_EVT
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmConfirm(BD_ADDR bd_addr, BOOLEAN accept);
+
+/*******************************************************************************
+**
+** Function BTA_DmPasskeyCancel
+**
+** Description This function is called to cancel the simple pairing process
+** reported by BTA_DM_SP_KEY_NOTIF_EVT
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmPasskeyCancel(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_DmAddDevice
+**
+** Description This function adds a device to the security database list
+** of peer devices. This function would typically be called
+** at system startup to initialize the security database with
+** known peer devices. This is a direct execution function
+** that may lock task scheduling on some platforms.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class,
+ LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
+ BOOLEAN is_trusted, UINT8 key_type,
+ tBTA_IO_CAP io_cap);
+
+/*******************************************************************************
+**
+** Function BTA_DmAddDevWithName
+**
+** Description This function is newer version of BTA_DmAddDevice()
+** which added bd_name and features as input parameters.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAddDevWithName (BD_ADDR bd_addr, DEV_CLASS dev_class,
+ BD_NAME bd_name, BD_FEATURES features,
+ LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
+ BOOLEAN is_trusted, UINT8 key_type, tBTA_IO_CAP io_cap);
+
+/*******************************************************************************
+**
+** Function BTA_DmRemoveDevice
+**
+** Description This function removes a device from the security database.
+** This is a direct execution function that may lock task
+** scheduling on some platforms.
+**
+**
+** Returns BTA_SUCCESS if successful.
+** BTA_FAIL if operation failed.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_DmAuthorizeReply
+**
+** Description This function provides an authorization reply when
+** authorization is requested by BTA. The application calls
+** this function after the security callback is called with
+** a BTA_DM_AUTHORIZE_EVT.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAuthorizeReply(BD_ADDR bd_addr, tBTA_SERVICE_ID service,
+ tBTA_AUTH_RESP response);
+
+/*******************************************************************************
+**
+** Function BTA_DmSignalStrength
+**
+** Description This function initiates RSSI and channnel quality
+** measurments. BTA_DM_SIG_STRENGTH_EVT is sent to
+** application with the values of RSSI and channel
+** quality
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSignalStrength(tBTA_SIG_STRENGTH_MASK mask, UINT16 period, BOOLEAN start);
+
+/*******************************************************************************
+**
+** Function BTA_DmWriteInqTxPower
+**
+** Description This command is used to write the inquiry transmit power level
+** used to transmit the inquiry (ID) data packets.
+**
+** Parameters tx_power - tx inquiry power to use, valid value is -70 ~ 20
+
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmWriteInqTxPower(INT8 tx_power);
+
+/*******************************************************************************
+**
+** Function BTA_DmEirAddUUID
+**
+** Description This function is called to add UUID into EIR.
+**
+** Parameters tBT_UUID - UUID
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmEirAddUUID (tBT_UUID *p_uuid);
+
+/*******************************************************************************
+**
+** Function BTA_DmEirRemoveUUID
+**
+** Description This function is called to remove UUID from EIR.
+**
+** Parameters tBT_UUID - UUID
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmEirRemoveUUID (tBT_UUID *p_uuid);
+
+/*******************************************************************************
+**
+** Function BTA_DmSetEIRConfig
+**
+** Description This function is called to override the BTA default EIR parameters.
+** This funciton is only valid in a system where BTU & App task
+** are in the same memory space.
+**
+** Parameters Pointer to User defined EIR config
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetEIRConfig (tBTA_DM_EIR_CONF *p_eir_cfg);
+
+/*******************************************************************************
+**
+** Function BTA_CheckEirData
+**
+** Description This function is called to get EIR data from significant part.
+**
+** Parameters p_eir - pointer of EIR significant part
+** type - finding EIR data type
+** p_length - return the length of EIR data
+**
+** Returns pointer of EIR data
+**
+*******************************************************************************/
+BTA_API extern UINT8 *BTA_CheckEirData( UINT8 *p_eir, UINT8 tag, UINT8 *p_length );
+
+/*******************************************************************************
+**
+** Function BTA_GetEirService
+**
+** Description This function is called to get BTA service mask from EIR.
+**
+** Parameters p_eir - pointer of EIR significant part
+** p_services - return the BTA service mask
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GetEirService( UINT8 *p_eir, tBTA_SERVICE_MASK *p_services );
+
+/*******************************************************************************
+**
+** Function BTA_DmUseSsr
+**
+** Description This function is called to check if the connected peer device
+** supports SSR or not.
+**
+** Returns TRUE, if SSR is supported
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_DmUseSsr( BD_ADDR bd_addr );
+
+
+/*******************************************************************************
+**
+** Function BTA_DmSetLocalDiRecord
+**
+** Description This function adds a DI record to the local SDP database.
+**
+** Returns BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmSetLocalDiRecord( tBTA_DI_RECORD *p_device_info,
+ UINT32 *p_handle );
+
+/*******************************************************************************
+**
+** Function BTA_DmGetLocalDiRecord
+**
+** Description Get a specified DI record to the local SDP database. If no
+** record handle is provided, the primary DI record will be
+** returned.
+**
+** Returns BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmGetLocalDiRecord( tBTA_DI_GET_RECORD *p_device_info,
+ UINT32 *p_handle );
+
+/*******************************************************************************
+**
+** Function BTA_DmDiDiscover
+**
+** Description This function queries a remote device for DI information.
+**
+** Returns None.
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiDiscover( BD_ADDR remote_device, tBTA_DISCOVERY_DB *p_db,
+ UINT32 len, tBTA_DM_SEARCH_CBACK *p_cback );
+
+/*******************************************************************************
+**
+** Function BTA_DmGetDiRecord
+**
+** Description This function retrieves a remote device's DI record from
+** the specified database.
+**
+** Returns None.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmGetDiRecord( UINT8 get_record_index, tBTA_DI_GET_RECORD *p_device_info,
+ tBTA_DISCOVERY_DB *p_db );
+
+/*******************************************************************************
+**
+** Function BTA_SysFeatures
+**
+** Description This function is called to set system features.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_SysFeatures (UINT16 sys_features);
+
+/*******************************************************************************
+**
+** Function bta_dmexecutecallback
+**
+** Description This function will request BTA to execute a call back in the context of BTU task
+** This API was named in lower case because it is only intended
+** for the internal customers(like BTIF).
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dmexecutecallback (tBTA_DM_EXEC_CBACK* p_callback, void * p_param);
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function BTA_DmPcmInitSamples
+**
+** Description initialize the down sample converter.
+**
+** src_sps: original samples per second (source audio data)
+** (ex. 44100, 48000)
+** bits: number of bits per pcm sample (16)
+** n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns none
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmPcmInitSamples (UINT32 src_sps, UINT32 bits, UINT32 n_channels);
+
+/**************************************************************************************
+** Function BTA_DmPcmResample
+**
+** Description Down sampling utility to convert higher sampling rate into 8K/16bits
+** PCM samples.
+**
+** Parameters p_src: pointer to the buffer where the original sampling PCM
+** are stored.
+** in_bytes: Length of the input PCM sample buffer in byte.
+** p_dst: pointer to the buffer which is to be used to store
+** the converted PCM samples.
+**
+**
+** Returns INT32: number of samples converted.
+**
+**************************************************************************************/
+BTA_API extern INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst);
+#endif
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+/* BLE related API functions */
+/*******************************************************************************
+**
+** Function BTA_DmBleSecurityGrant
+**
+** Description Grant security request access.
+**
+** Parameters: bd_addr - BD address of the peer
+** res - security grant status.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSecurityGrant(BD_ADDR bd_addr, tBTA_DM_BLE_SEC_GRANT res);
+
+
+
+/*******************************************************************************
+**
+** Function BTA_DmBleSetBgConnType
+**
+** Description This function is called to set BLE connectable mode for a
+** peripheral device.
+**
+** Parameters bg_conn_type: it can be auto connection, or selective connection.
+** p_select_cback: callback function when selective connection procedure
+** is being used.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSetBgConnType(tBTA_DM_BLE_CONN_TYPE bg_conn_type, tBTA_DM_BLE_SEL_CBACK *p_select_cback);
+
+/*******************************************************************************
+**
+** Function BTA_DmBlePasskeyReply
+**
+** Description Send BLE SMP passkey reply.
+**
+** Parameters: bd_addr - BD address of the peer
+** accept - passkey entry sucessful or declined.
+** passkey - passkey value, must be a 6 digit number,
+** can be lead by 0.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passkey);
+
+/*******************************************************************************
+**
+** Function BTA_DmAddBleDevice
+**
+** Description Add a BLE device. This function will be normally called
+** during host startup to restore all required information
+** for a LE device stored in the NVRAM.
+**
+** Parameters: bd_addr - BD address of the peer
+** dev_type - Remote device's device type.
+** addr_type - LE device address type.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAddBleDevice(BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type,
+ tBT_DEVICE_TYPE dev_type);
+
+
+/*******************************************************************************
+**
+** Function BTA_DmAddBleKey
+**
+** Description Add/modify LE device information. This function will be
+** normally called during host startup to restore all required
+** information stored in the NVRAM.
+**
+** Parameters: bd_addr - BD address of the peer
+** p_le_key - LE key values.
+** key_type - LE SMP key type.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAddBleKey (BD_ADDR bd_addr, tBTA_LE_KEY_VALUE *p_le_key,
+ tBTA_LE_KEY_TYPE key_type);
+
+/*******************************************************************************
+**
+** Function BTA_DmSetBlePrefConnParams
+**
+** Description This function is called to set the preferred connection
+** parameters when default connection parameter is not desired.
+**
+** Parameters: bd_addr - BD address of the peripheral
+** min_conn_int - minimum preferred connection interval
+** max_conn_int - maximum preferred connection interval
+** slave_latency - preferred slave latency
+** supervision_tout - preferred supervision timeout
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr,
+ UINT16 min_conn_int, UINT16 max_conn_int,
+ UINT16 slave_latency, UINT16 supervision_tout );
+
+/*******************************************************************************
+**
+** Function BTA_DmSetBleConnScanParams
+**
+** Description This function is called to set scan parameters used in
+** BLE connection request
+**
+** Parameters: bd_addr - BD address of the peripheral
+** scan_interval - scan interval
+** scan_window - scan window
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetBleConnScanParams(UINT16 scan_interval,
+ UINT16 scan_window );
+
+/*******************************************************************************
+**
+** Function BTA_DmSearchExt
+**
+** Description This function searches for peer Bluetooth devices. It performs
+** an inquiry and gets the remote name for devices. Service
+** discovery is done if services is non zero
+**
+** Parameters p_dm_inq: inquiry conditions
+** services: if service is not empty, service discovery will be done.
+** for all GATT based service condition, put num_uuid, and
+** p_uuid is the pointer to the list of UUID values.
+** p_cback: callback functino when search is completed.
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSearchExt(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK_EXT *p_services,
+ tBTA_DM_SEARCH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_DmDiscoverExt
+**
+** Description This function does service discovery for services of a
+** peer device. When services.num_uuid is 0, it indicates all
+** GATT based services are to be searched; other wise a list of
+** UUID of interested services should be provided through
+** services.p_uuid.
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+ tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+
+/*******************************************************************************
+**
+** Function BTA_DmSetEncryption
+**
+** Description This function is called to ensure that connection is
+** encrypted. Should be called only on an open connection.
+** Typically only needed for connections that first want to
+** bring up unencrypted links, then later encrypt them.
+**
+** Parameters: bd_addr - Address of the peer device
+** p_callback - Pointer to callback function to indicat the
+** link encryption status
+** sec_act - This is the security action to indicate
+** what knid of BLE security level is required for
+** the BLE link if the BLE is supported
+** Note: This parameter is ignored for the BR/EDR link
+** or the BLE is not supported
+**
+** Returns void
+**
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
+ tBTA_DM_BLE_SEC_ACT sec_act);
+
+#endif
+
+// btla-specific ++
+/*******************************************************************************
+**
+** Function BTA_DmSetAfhChannelAssessment
+**
+** Description This function is called to set the channel assessment mode on or off
+**
+** Returns status
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetAfhChannelAssessment (BOOLEAN enable_or_disable);
+// btla-specific --
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_API_H */
+
diff --git a/bta/include/bta_ar_api.h b/bta/include/bta_ar_api.h
new file mode 100644
index 0000000..b451cb4
--- /dev/null
+++ b/bta/include/bta_ar_api.h
@@ -0,0 +1,140 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the simulatenous advanced
+ * audio/video streaming (AV) source and sink of BTA, Broadcom's Bluetooth
+ * application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_AR_API_H
+#define BTA_AR_API_H
+
+#include "avdt_api.h"
+#include "avct_api.h"
+#include "avrc_api.h"
+#include "sdp_api.h"
+#include "bta_av_api.h"
+#include "bta_sys.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+/* This event signal to AR user that other profile is connected */
+#define BTA_AR_AVDT_CONN_EVT (AVDT_MAX_EVT + 1)
+
+/*******************************************************************************
+**
+** Function bta_ar_init
+**
+** Description This function is called from bta_sys_init().
+** to initialize the control block
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bta_ar_init(void);
+
+/*******************************************************************************
+**
+** Function bta_ar_reg_avdt
+**
+** Description This function is called to register to AVDTP.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bta_ar_reg_avdt(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback, tBTA_SYS_ID sys_id);
+
+/*******************************************************************************
+**
+** Function bta_ar_dereg_avdt
+**
+** Description This function is called to de-register from AVDTP.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bta_ar_dereg_avdt(tBTA_SYS_ID sys_id);
+
+/*******************************************************************************
+**
+** Function bta_ar_avdt_conn
+**
+** Description This function is called to let ar know that some AVDTP profile
+** is connected for this sys_id.
+** If the other sys modules started a timer for PENDING_EVT,
+** the timer can be stopped now.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function bta_ar_reg_avct
+**
+** Description This function is called to register to AVCTP.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bta_ar_reg_avct(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask, tBTA_SYS_ID sys_id);
+
+/*******************************************************************************
+**
+** Function bta_ar_dereg_avct
+**
+** Description This function is called to deregister from AVCTP.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bta_ar_dereg_avct(tBTA_SYS_ID sys_id);
+
+/******************************************************************************
+**
+** Function bta_ar_reg_avrc
+**
+** Description This function is called to register an SDP record for AVRCP.
+**
+** Returns void
+**
+******************************************************************************/
+extern void bta_ar_reg_avrc(UINT16 service_uuid, char *p_service_name,
+ char *p_provider_name, UINT16 categories, tBTA_SYS_ID sys_id);
+
+/******************************************************************************
+**
+** Function bta_ar_dereg_avrc
+**
+** Description This function is called to de-register/delete an SDP record for AVRCP.
+**
+** Returns void
+**
+******************************************************************************/
+extern void bta_ar_dereg_avrc(UINT16 service_uuid, tBTA_SYS_ID sys_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AR_API_H */
diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h
new file mode 100644
index 0000000..eb77279
--- /dev/null
+++ b/bta/include/bta_av_api.h
@@ -0,0 +1,765 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the advanced audio/video streaming
+ * (AV) subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ * phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_API_H
+#define BTA_AV_API_H
+
+#include "avrc_api.h"
+#include "avdt_api.h"
+#include "a2d_api.h"
+#include "bta_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+/* Set to TRUE if seperate authorization prompt desired for AVCTP besides A2DP authorization */
+/* Typically FALSE when AVRCP is used in conjunction with A2DP */
+#ifndef BTA_AV_WITH_AVCTP_AUTHORIZATION
+#define BTA_AV_WITH_AVCTP_AUTHORIZATION FALSE
+#endif
+
+/* AV status values */
+#define BTA_AV_SUCCESS 0 /* successful operation */
+#define BTA_AV_FAIL 1 /* generic failure */
+#define BTA_AV_FAIL_SDP 2 /* service not found */
+#define BTA_AV_FAIL_STREAM 3 /* stream connection failed */
+#define BTA_AV_FAIL_RESOURCES 4 /* no resources */
+#define BTA_AV_FAIL_ROLE 5 /* failed due to role management related issues */
+
+typedef UINT8 tBTA_AV_STATUS;
+
+/* AV features masks */
+#define BTA_AV_FEAT_RCTG 0x0001 /* remote control target */
+#define BTA_AV_FEAT_RCCT 0x0002 /* remote control controller */
+#define BTA_AV_FEAT_PROTECT 0x0004 /* streaming media contect protection */
+#define BTA_AV_FEAT_VENDOR 0x0008 /* remote control vendor dependent commands */
+#define BTA_AV_FEAT_REPORT 0x0020 /* use reporting service for VDP */
+#define BTA_AV_FEAT_METADATA 0x0040 /* remote control Metadata Transfer command/response */
+#define BTA_AV_FEAT_MULTI_AV 0x0080 /* use multi-av, if controller supports it */
+#define BTA_AV_FEAT_BROWSE 0x0010 /* use browsing channel */
+#define BTA_AV_FEAT_MASTER 0x0100 /* stream only as master role */
+#define BTA_AV_FEAT_ADV_CTRL 0x0200 /* remote control Advanced Control command/response */
+#define BTA_AV_FEAT_DELAY_RPT 0x0400 /* allow delay reporting */
+#define BTA_AV_FEAT_ACP_START 0x0800 /* start stream when 2nd SNK was accepted */
+
+/* Internal features */
+#define BTA_AV_FEAT_NO_SCO_SSPD 0x8000 /* Do not suspend av streaming as to AG events(SCO or Call) */
+
+typedef UINT16 tBTA_AV_FEAT;
+
+/* AV channel values */
+#define BTA_AV_CHNL_MSK 0xC0
+#define BTA_AV_CHNL_AUDIO 0x40 /* audio channel */
+#define BTA_AV_CHNL_VIDEO 0x80 /* video channel */
+typedef UINT8 tBTA_AV_CHNL;
+
+
+#define BTA_AV_HNDL_MSK 0x3F
+typedef UINT8 tBTA_AV_HNDL;
+/* handle index to mask */
+#define BTA_AV_HNDL_TO_MSK(h) ((UINT8)(1 << (h)))
+
+/* tBTA_AV_HNDL to mask */
+#define BTA_AV_HNDL_TYPE_TO_MSK(h) ((UINT8)(1 << (h&BTA_AV_HNDL_MSK)))
+
+/* offset of codec type in codec info byte array */
+#define BTA_AV_CODEC_TYPE_IDX AVDT_CODEC_TYPE_INDEX /* 2 */
+
+
+
+/* maximum number of streams created: 1 for audio, 1 for video */
+#ifndef BTA_AV_NUM_STRS
+#define BTA_AV_NUM_STRS 2
+#endif
+
+#ifndef BTA_AV_MAX_SEPS
+#define BTA_AV_MAX_SEPS 2
+#endif
+
+#ifndef BTA_AV_MAX_A2DP_MTU
+ /*#define BTA_AV_MAX_A2DP_MTU 668 //224 (DM5) * 3 - 4(L2CAP header) */
+#define BTA_AV_MAX_A2DP_MTU 1008
+#endif
+
+#ifndef BTA_AV_MAX_VDP_MTU
+#define BTA_AV_MAX_VDP_MTU 1008
+#endif
+
+
+/* codec type */
+#define BTA_AV_CODEC_SBC A2D_MEDIA_CT_SBC /* SBC media codec type */
+#define BTA_AV_CODEC_M12 A2D_MEDIA_CT_M12 /* MPEG-1, 2 Audio media codec type */
+#define BTA_AV_CODEC_M24 A2D_MEDIA_CT_M24 /* MPEG-2, 4 AAC media codec type */
+#define BTA_AV_CODEC_ATRAC A2D_MEDIA_CT_ATRAC /* ATRAC family media codec type */
+#define BTA_AV_CODEC_H263_P0 VDP_MEDIA_CT_H263_P0 /* H.263 baseline (profile 0) */
+#define BTA_AV_CODEC_MPEG4 VDP_MEDIA_CT_MPEG4 /* MPEG-4 Visual Simple Profile */
+#define BTA_AV_CODEC_H263_P3 VDP_MEDIA_CT_H263_P3 /* H.263 profile 3 */
+#define BTA_AV_CODEC_H263_P8 VDP_MEDIA_CT_H263_P8 /* H.263 profile 8 */
+#define BTA_AV_CODEC_VEND VDP_MEDIA_CT_VEND /* Non-VDP */
+
+typedef UINT8 tBTA_AV_CODEC;
+
+/* Company ID in BT assigned numbers */
+#define BTA_AV_BT_VENDOR_ID VDP_BT_VENDOR_ID /* Broadcom Corporation */
+
+/* vendor specific codec ID */
+#define BTA_AV_CODEC_ID_H264 VDP_CODEC_ID_H264 /* Non-VDP codec ID - H.264 */
+#define BTA_AV_CODEC_ID_IMG VDP_CODEC_ID_IMG /* Non-VDP codec ID - images/slideshow */
+
+/* operation id list for BTA_AvRemoteCmd */
+#define BTA_AV_RC_SELECT AVRC_ID_SELECT /* select */
+#define BTA_AV_RC_UP AVRC_ID_UP /* up */
+#define BTA_AV_RC_DOWN AVRC_ID_DOWN /* down */
+#define BTA_AV_RC_LEFT AVRC_ID_LEFT /* left */
+#define BTA_AV_RC_RIGHT AVRC_ID_RIGHT /* right */
+#define BTA_AV_RC_RIGHT_UP AVRC_ID_RIGHT_UP /* right-up */
+#define BTA_AV_RC_RIGHT_DOWN AVRC_ID_RIGHT_DOWN /* right-down */
+#define BTA_AV_RC_LEFT_UP AVRC_ID_LEFT_UP /* left-up */
+#define BTA_AV_RC_LEFT_DOWN AVRC_ID_LEFT_DOWN /* left-down */
+#define BTA_AV_RC_ROOT_MENU AVRC_ID_ROOT_MENU /* root menu */
+#define BTA_AV_RC_SETUP_MENU AVRC_ID_SETUP_MENU /* setup menu */
+#define BTA_AV_RC_CONT_MENU AVRC_ID_CONT_MENU /* contents menu */
+#define BTA_AV_RC_FAV_MENU AVRC_ID_FAV_MENU /* favorite menu */
+#define BTA_AV_RC_EXIT AVRC_ID_EXIT /* exit */
+#define BTA_AV_RC_0 AVRC_ID_0 /* 0 */
+#define BTA_AV_RC_1 AVRC_ID_1 /* 1 */
+#define BTA_AV_RC_2 AVRC_ID_2 /* 2 */
+#define BTA_AV_RC_3 AVRC_ID_3 /* 3 */
+#define BTA_AV_RC_4 AVRC_ID_4 /* 4 */
+#define BTA_AV_RC_5 AVRC_ID_5 /* 5 */
+#define BTA_AV_RC_6 AVRC_ID_6 /* 6 */
+#define BTA_AV_RC_7 AVRC_ID_7 /* 7 */
+#define BTA_AV_RC_8 AVRC_ID_8 /* 8 */
+#define BTA_AV_RC_9 AVRC_ID_9 /* 9 */
+#define BTA_AV_RC_DOT AVRC_ID_DOT /* dot */
+#define BTA_AV_RC_ENTER AVRC_ID_ENTER /* enter */
+#define BTA_AV_RC_CLEAR AVRC_ID_CLEAR /* clear */
+#define BTA_AV_RC_CHAN_UP AVRC_ID_CHAN_UP /* channel up */
+#define BTA_AV_RC_CHAN_DOWN AVRC_ID_CHAN_DOWN /* channel down */
+#define BTA_AV_RC_PREV_CHAN AVRC_ID_PREV_CHAN /* previous channel */
+#define BTA_AV_RC_SOUND_SEL AVRC_ID_SOUND_SEL /* sound select */
+#define BTA_AV_RC_INPUT_SEL AVRC_ID_INPUT_SEL /* input select */
+#define BTA_AV_RC_DISP_INFO AVRC_ID_DISP_INFO /* display information */
+#define BTA_AV_RC_HELP AVRC_ID_HELP /* help */
+#define BTA_AV_RC_PAGE_UP AVRC_ID_PAGE_UP /* page up */
+#define BTA_AV_RC_PAGE_DOWN AVRC_ID_PAGE_DOWN /* page down */
+#define BTA_AV_RC_POWER AVRC_ID_POWER /* power */
+#define BTA_AV_RC_VOL_UP AVRC_ID_VOL_UP /* volume up */
+#define BTA_AV_RC_VOL_DOWN AVRC_ID_VOL_DOWN /* volume down */
+#define BTA_AV_RC_MUTE AVRC_ID_MUTE /* mute */
+#define BTA_AV_RC_PLAY AVRC_ID_PLAY /* play */
+#define BTA_AV_RC_STOP AVRC_ID_STOP /* stop */
+#define BTA_AV_RC_PAUSE AVRC_ID_PAUSE /* pause */
+#define BTA_AV_RC_RECORD AVRC_ID_RECORD /* record */
+#define BTA_AV_RC_REWIND AVRC_ID_REWIND /* rewind */
+#define BTA_AV_RC_FAST_FOR AVRC_ID_FAST_FOR /* fast forward */
+#define BTA_AV_RC_EJECT AVRC_ID_EJECT /* eject */
+#define BTA_AV_RC_FORWARD AVRC_ID_FORWARD /* forward */
+#define BTA_AV_RC_BACKWARD AVRC_ID_BACKWARD /* backward */
+#define BTA_AV_RC_ANGLE AVRC_ID_ANGLE /* angle */
+#define BTA_AV_RC_SUBPICT AVRC_ID_SUBPICT /* subpicture */
+#define BTA_AV_RC_F1 AVRC_ID_F1 /* F1 */
+#define BTA_AV_RC_F2 AVRC_ID_F2 /* F2 */
+#define BTA_AV_RC_F3 AVRC_ID_F3 /* F3 */
+#define BTA_AV_RC_F4 AVRC_ID_F4 /* F4 */
+#define BTA_AV_RC_F5 AVRC_ID_F5 /* F5 */
+#define BTA_AV_VENDOR AVRC_ID_VENDOR /* vendor unique */
+
+typedef UINT8 tBTA_AV_RC;
+
+/* state flag for pass through command */
+#define BTA_AV_STATE_PRESS AVRC_STATE_PRESS /* key pressed */
+#define BTA_AV_STATE_RELEASE AVRC_STATE_RELEASE /* key released */
+
+typedef UINT8 tBTA_AV_STATE;
+
+/* command codes for BTA_AvVendorCmd */
+#define BTA_AV_CMD_CTRL AVRC_CMD_CTRL
+#define BTA_AV_CMD_STATUS AVRC_CMD_STATUS
+#define BTA_AV_CMD_SPEC_INQ AVRC_CMD_SPEC_INQ
+#define BTA_AV_CMD_NOTIF AVRC_CMD_NOTIF
+#define BTA_AV_CMD_GEN_INQ AVRC_CMD_GEN_INQ
+
+typedef UINT8 tBTA_AV_CMD;
+
+/* response codes for BTA_AvVendorRsp */
+#define BTA_AV_RSP_NOT_IMPL AVRC_RSP_NOT_IMPL
+#define BTA_AV_RSP_ACCEPT AVRC_RSP_ACCEPT
+#define BTA_AV_RSP_REJ AVRC_RSP_REJ
+#define BTA_AV_RSP_IN_TRANS AVRC_RSP_IN_TRANS
+#define BTA_AV_RSP_IMPL_STBL AVRC_RSP_IMPL_STBL
+#define BTA_AV_RSP_CHANGED AVRC_RSP_CHANGED
+#define BTA_AV_RSP_INTERIM AVRC_RSP_INTERIM
+
+typedef UINT8 tBTA_AV_CODE;
+
+/* error codes for BTA_AvProtectRsp */
+#define BTA_AV_ERR_NONE A2D_SUCCESS /* Success, no error */
+#define BTA_AV_ERR_BAD_STATE AVDT_ERR_BAD_STATE /* Message cannot be processed in this state */
+#define BTA_AV_ERR_RESOURCE AVDT_ERR_RESOURCE /* Insufficient resources */
+#define BTA_AV_ERR_BAD_CP_TYPE A2D_BAD_CP_TYPE /* The requested Content Protection Type is not supported */
+#define BTA_AV_ERR_BAD_CP_FORMAT A2D_BAD_CP_FORMAT /* The format of Content Protection Data is not correct */
+
+typedef UINT8 tBTA_AV_ERR;
+
+
+/* AV callback events */
+#define BTA_AV_ENABLE_EVT 0 /* AV enabled */
+#define BTA_AV_REGISTER_EVT 1 /* registered to AVDT */
+#define BTA_AV_OPEN_EVT 2 /* connection opened */
+#define BTA_AV_CLOSE_EVT 3 /* connection closed */
+#define BTA_AV_START_EVT 4 /* stream data transfer started */
+#define BTA_AV_STOP_EVT 5 /* stream data transfer stopped */
+#define BTA_AV_PROTECT_REQ_EVT 6 /* content protection request */
+#define BTA_AV_PROTECT_RSP_EVT 7 /* content protection response */
+#define BTA_AV_RC_OPEN_EVT 8 /* remote control channel open */
+#define BTA_AV_RC_CLOSE_EVT 9 /* remote control channel closed */
+#define BTA_AV_REMOTE_CMD_EVT 10 /* remote control command */
+#define BTA_AV_REMOTE_RSP_EVT 11 /* remote control response */
+#define BTA_AV_VENDOR_CMD_EVT 12 /* vendor dependent remote control command */
+#define BTA_AV_VENDOR_RSP_EVT 13 /* vendor dependent remote control response */
+#define BTA_AV_RECONFIG_EVT 14 /* reconfigure response */
+#define BTA_AV_SUSPEND_EVT 15 /* suspend response */
+#define BTA_AV_PENDING_EVT 16 /* incoming connection pending:
+ * signal channel is open and stream is not open
+ * after BTA_AV_SIG_TIME_VAL ms */
+#define BTA_AV_META_MSG_EVT 17 /* metadata messages */
+#define BTA_AV_REJECT_EVT 18 /* incoming connection rejected */
+#define BTA_AV_RC_FEAT_EVT 19 /* remote control channel peer supported features update */
+/* Max BTA event */
+#define BTA_AV_MAX_EVT 20
+
+typedef UINT8 tBTA_AV_EVT;
+
+/* Event associated with BTA_AV_ENABLE_EVT */
+typedef struct
+{
+ tBTA_AV_FEAT features;
+} tBTA_AV_ENABLE;
+
+/* Event associated with BTA_AV_REGISTER_EVT */
+typedef struct
+{
+ tBTA_AV_CHNL chnl; /* audio/video */
+ tBTA_AV_HNDL hndl; /* Handle associated with the stream. */
+ UINT8 app_id; /* ID associated with call to BTA_AvRegister() */
+ tBTA_AV_STATUS status;
+} tBTA_AV_REGISTER;
+
+/* data associated with BTA_AV_OPEN_EVT */
+#define BTA_AV_EDR_2MBPS 0x01
+#define BTA_AV_EDR_3MBPS 0x02
+typedef UINT8 tBTA_AV_EDR;
+
+typedef struct
+{
+ tBTA_AV_CHNL chnl;
+ tBTA_AV_HNDL hndl;
+ BD_ADDR bd_addr;
+ tBTA_AV_STATUS status;
+ BOOLEAN starting;
+ tBTA_AV_EDR edr; /* 0, if peer device does not support EDR */
+} tBTA_AV_OPEN;
+
+/* data associated with BTA_AV_CLOSE_EVT */
+typedef struct
+{
+ tBTA_AV_CHNL chnl;
+ tBTA_AV_HNDL hndl;
+} tBTA_AV_CLOSE;
+
+/* data associated with BTA_AV_START_EVT */
+typedef struct
+{
+ tBTA_AV_CHNL chnl;
+ tBTA_AV_HNDL hndl;
+ tBTA_AV_STATUS status;
+ BOOLEAN initiator; /* TRUE, if local device initiates the START */
+ BOOLEAN suspending;
+} tBTA_AV_START;
+
+/* data associated with BTA_AV_SUSPEND_EVT */
+typedef struct
+{
+ tBTA_AV_CHNL chnl;
+ tBTA_AV_HNDL hndl;
+ BOOLEAN initiator; /* TRUE, if local device initiates the SUSPEND */
+ tBTA_AV_STATUS status;
+} tBTA_AV_SUSPEND;
+
+/* data associated with BTA_AV_RECONFIG_EVT */
+typedef struct
+{
+ tBTA_AV_CHNL chnl;
+ tBTA_AV_HNDL hndl;
+ tBTA_AV_STATUS status;
+} tBTA_AV_RECONFIG;
+
+/* data associated with BTA_AV_PROTECT_REQ_EVT */
+typedef struct
+{
+ tBTA_AV_CHNL chnl;
+ tBTA_AV_HNDL hndl;
+ UINT8 *p_data;
+ UINT16 len;
+} tBTA_AV_PROTECT_REQ;
+
+/* data associated with BTA_AV_PROTECT_RSP_EVT */
+typedef struct
+{
+ tBTA_AV_CHNL chnl;
+ tBTA_AV_HNDL hndl;
+ UINT8 *p_data;
+ UINT16 len;
+ tBTA_AV_ERR err_code;
+} tBTA_AV_PROTECT_RSP;
+
+/* data associated with BTA_AV_RC_OPEN_EVT */
+typedef struct
+{
+ UINT8 rc_handle;
+ tBTA_AV_FEAT peer_features;
+ BD_ADDR peer_addr;
+ tBTA_AV_STATUS status;
+} tBTA_AV_RC_OPEN;
+
+/* data associated with BTA_AV_RC_CLOSE_EVT */
+typedef struct
+{
+ UINT8 rc_handle;
+ BD_ADDR peer_addr;
+} tBTA_AV_RC_CLOSE;
+
+/* data associated with BTA_AV_RC_FEAT_EVT */
+typedef struct
+{
+ UINT8 rc_handle;
+ tBTA_AV_FEAT peer_features;
+} tBTA_AV_RC_FEAT;
+
+/* data associated with BTA_AV_REMOTE_CMD_EVT */
+typedef struct
+{
+ UINT8 rc_handle;
+ tBTA_AV_RC rc_id;
+ tBTA_AV_STATE key_state;
+ UINT8 len;
+ UINT8 *p_data;
+ tAVRC_HDR hdr; /* Message header. */
+ UINT8 label;
+} tBTA_AV_REMOTE_CMD;
+
+/* data associated with BTA_AV_REMOTE_RSP_EVT */
+typedef struct
+{
+ UINT8 rc_handle;
+ tBTA_AV_RC rc_id;
+ tBTA_AV_STATE key_state;
+ UINT8 len;
+ UINT8 *p_data;
+ tBTA_AV_CODE rsp_code;
+ UINT8 label;
+} tBTA_AV_REMOTE_RSP;
+
+/* data associated with BTA_AV_VENDOR_CMD_EVT, BTA_AV_VENDOR_RSP_EVT */
+typedef struct
+{
+ UINT8 rc_handle;
+ UINT16 len; /* Max vendor dependent message is 512 */
+ UINT8 label;
+ tBTA_AV_CODE code;
+ UINT32 company_id;
+ UINT8 *p_data;
+} tBTA_AV_VENDOR;
+
+/* data associated with BTA_AV_META_MSG_EVT */
+typedef struct
+{
+ UINT8 rc_handle;
+ UINT16 len;
+ UINT8 label;
+ tBTA_AV_CODE code;
+ UINT32 company_id;
+ UINT8 *p_data;
+ tAVRC_MSG *p_msg;
+} tBTA_AV_META_MSG;
+
+/* data associated with BTA_AV_PENDING_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr;
+} tBTA_AV_PEND;
+
+/* data associated with BTA_AV_REJECT_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr;
+ tBTA_AV_HNDL hndl; /* Handle associated with the stream that rejected the connection. */
+} tBTA_AV_REJECT;
+
+
+/* union of data associated with AV callback */
+typedef union
+{
+ tBTA_AV_CHNL chnl;
+ tBTA_AV_ENABLE enable;
+ tBTA_AV_REGISTER registr;
+ tBTA_AV_OPEN open;
+ tBTA_AV_CLOSE close;
+ tBTA_AV_START start;
+ tBTA_AV_PROTECT_REQ protect_req;
+ tBTA_AV_PROTECT_RSP protect_rsp;
+ tBTA_AV_RC_OPEN rc_open;
+ tBTA_AV_RC_CLOSE rc_close;
+ tBTA_AV_REMOTE_CMD remote_cmd;
+ tBTA_AV_REMOTE_RSP remote_rsp;
+ tBTA_AV_VENDOR vendor_cmd;
+ tBTA_AV_VENDOR vendor_rsp;
+ tBTA_AV_RECONFIG reconfig;
+ tBTA_AV_SUSPEND suspend;
+ tBTA_AV_PEND pend;
+ tBTA_AV_META_MSG meta_msg;
+ tBTA_AV_REJECT reject;
+ tBTA_AV_RC_FEAT rc_feat;
+} tBTA_AV;
+
+
+#define BTA_AVC_PACKET_LEN AVRC_PACKET_LEN
+#define BTA_VENDOR_DATA_OFFSET 6
+#define BTA_VENDOR_HEADER_LEN 4
+#define BTA_MAX_VENDOR_DEPENDENT_DATA_LEN (BTA_AVC_PACKET_LEN-BTA_VENDOR_DATA_OFFSET-BTA_VENDOR_HEADER_LEN)
+#define BTA_GROUP_NAVI_MSG_OP_DATA_LEN 5
+
+#define BTA_ERROR_INVALID_CMD AVRC_STS_BAD_CMD
+#define BTA_ERROR_INVALID_PARAM AVRC_STS_BAD_PARAM
+#define BTA_ERROR_BAD_CONTENTS AVRC_STS_NOT_FOUND
+#define BTA_ERROR_INTERNAL AVRC_STS_INTERNAL_ERR
+
+#define BTA_AV_META_SINGLE_PACKET AVRC_PKT_SINGLE
+
+#define BTA_AV_CO_METADATA AVRC_CO_METADATA
+
+/* AV callback */
+typedef void (tBTA_AV_CBACK)(tBTA_AV_EVT event, tBTA_AV *p_data);
+
+/* type for stream state machine action functions */
+typedef void (*tBTA_AV_ACT)(void *p_cb, void *p_data);
+
+/* type for registering VDP */
+typedef void (tBTA_AV_REG) (tAVDT_CS *p_cs, char *p_service_name, void *p_data);
+
+/* AV configuration structure */
+typedef struct
+{
+ UINT32 company_id; /* AVRCP Company ID */
+ UINT16 avrc_mtu; /* AVRCP MTU at L2CAP for control channel */
+ UINT16 avrc_br_mtu; /* AVRCP MTU at L2CAP for browsing channel */
+ UINT16 avrc_ct_cat; /* AVRCP controller categories */
+ UINT16 avrc_tg_cat; /* AVRCP target categories */
+ UINT16 sig_mtu; /* AVDTP signaling channel MTU at L2CAP */
+ UINT16 audio_mtu; /* AVDTP audio transport channel MTU at L2CAP */
+ const UINT16 *p_audio_flush_to;/* AVDTP audio transport channel flush timeout */
+ UINT16 audio_mqs; /* AVDTP audio channel max data queue size */
+ UINT16 video_mtu; /* AVDTP video transport channel MTU at L2CAP */
+ UINT16 video_flush_to; /* AVDTP video transport channel flush timeout */
+ BOOLEAN avrc_group; /* TRUE, to accept AVRC 1.3 group nevigation command */
+ UINT8 num_co_ids; /* company id count in p_meta_co_ids */
+ UINT8 num_evt_ids; /* event id count in p_meta_evt_ids */
+ tBTA_AV_CODE rc_pass_rsp; /* the default response code for pass through commands */
+ const UINT32 *p_meta_co_ids;/* the metadata Get Capabilities response for company id */
+ const UINT8 *p_meta_evt_ids;/* the the metadata Get Capabilities response for event id */
+ const tBTA_AV_ACT *p_act_tbl;/* the action function table for VDP stream */
+ tBTA_AV_REG *p_reg; /* action function to register VDP */
+} tBTA_AV_CFG;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function BTA_AvEnable
+**
+** Description Enable the advanced audio/video service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_AV_ENABLE_EVT. This function must
+** be called before other function in the AV API are
+** called.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvEnable(tBTA_SEC sec_mask, tBTA_AV_FEAT features,
+ tBTA_AV_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_AvDisable
+**
+** Description Disable the advanced audio/video service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_AvRegister
+**
+** Description Register the audio or video service to stack. When the
+** operation is complete the callback function will be
+** called with a BTA_AV_REGISTER_EVT. This function must
+** be called before AVDT stream is open.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name,
+ UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_AvDeregister
+**
+** Description Deregister the audio or video service
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvDeregister(tBTA_AV_HNDL hndl);
+
+/*******************************************************************************
+**
+** Function BTA_AvOpen
+**
+** Description Opens an advanced audio/video connection to a peer device.
+** When connection is open callback function is called
+** with a BTA_AV_OPEN_EVT.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle,
+ BOOLEAN use_rc, tBTA_SEC sec_mask);
+
+/*******************************************************************************
+**
+** Function BTA_AvClose
+**
+** Description Close the current streams.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvClose(tBTA_AV_HNDL handle);
+
+/*******************************************************************************
+**
+** Function BTA_AvDisconnect
+**
+** Description Close the connection to the address.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvDisconnect(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_AvStart
+**
+** Description Start audio/video stream data transfer.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvStart(void);
+
+/*******************************************************************************
+**
+** Function BTA_AvStop
+**
+** Description Stop audio/video stream data transfer.
+** If suspend is TRUE, this function sends AVDT suspend signal
+** to the connected peer(s).
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvStop(BOOLEAN suspend);
+
+/*******************************************************************************
+**
+** Function BTA_AvReconfig
+**
+** Description Reconfigure the audio/video stream.
+** If suspend is TRUE, this function tries the suspend/reconfigure
+** procedure first.
+** If suspend is FALSE or when suspend/reconfigure fails,
+** this function closes and re-opens the AVDT connection.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvReconfig(tBTA_AV_HNDL hndl, BOOLEAN suspend, UINT8 sep_info_idx,
+ UINT8 *p_codec_info, UINT8 num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function BTA_AvProtectReq
+**
+** Description Send a content protection request. This function can only
+** be used if AV is enabled with feature BTA_AV_FEAT_PROTECT.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_AvProtectRsp
+**
+** Description Send a content protection response. This function must
+** be called if a BTA_AV_PROTECT_REQ_EVT is received.
+** This function can only be used if AV is enabled with
+** feature BTA_AV_FEAT_PROTECT.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvProtectRsp(tBTA_AV_HNDL hndl, UINT8 error_code, UINT8 *p_data,
+ UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_AvRemoteCmd
+**
+** Description Send a remote control command. This function can only
+** be used if AV is enabled with feature BTA_AV_FEAT_RCCT.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvRemoteCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_RC rc_id,
+ tBTA_AV_STATE key_state);
+
+/*******************************************************************************
+**
+** Function BTA_AvVendorCmd
+**
+** Description Send a vendor dependent remote control command. This
+** function can only be used if AV is enabled with feature
+** BTA_AV_FEAT_VENDOR.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code,
+ UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_AvVendorRsp
+**
+** Description Send a vendor dependent remote control response.
+** This function must be called if a BTA_AV_VENDOR_CMD_EVT
+** is received. This function can only be used if AV is
+** enabled with feature BTA_AV_FEAT_VENDOR.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvVendorRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
+ UINT8 *p_data, UINT16 len, UINT32 company_id);
+
+
+/*******************************************************************************
+**
+** Function BTA_AvOpenRc
+**
+** Description Open an AVRCP connection toward the device with the
+** specified handle
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvOpenRc(tBTA_AV_HNDL handle);
+
+/*******************************************************************************
+**
+** Function BTA_AvCloseRc
+**
+** Description Close an AVRCP connection
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvCloseRc(UINT8 rc_handle);
+
+/*******************************************************************************
+**
+** Function BTA_AvMetaRsp
+**
+** Description Send a Metadata command/response. The message contained
+** in p_pkt can be composed with AVRC utility functions.
+** This function can only be used if AV is enabled with feature
+** BTA_AV_FEAT_METADATA.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvMetaRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
+ BT_HDR *p_pkt);
+
+/*******************************************************************************
+**
+** Function BTA_AvMetaCmd
+**
+** Description Send a Metadata/Advanced Control command. The message contained
+** in p_pkt can be composed with AVRC utility functions.
+** This function can only be used if AV is enabled with feature
+** BTA_AV_FEAT_METADATA.
+** This message is sent only when the peer supports the TG role.
+*8 The only command makes sense right now is the absolute volume command.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p_pkt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AV_API_H */
diff --git a/bta/include/bta_av_ci.h b/bta/include/bta_av_ci.h
new file mode 100644
index 0000000..63668a9
--- /dev/null
+++ b/bta/include/bta_av_ci.h
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for advanced audio/video call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_CI_H
+#define BTA_AV_CI_H
+
+#include "bta_av_api.h"
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_av_ci_src_data_ready
+**
+** Description This function sends an event to the AV indicating that
+** the phone has audio stream data ready to send and AV
+** should call bta_av_co_audio_src_data_path() or
+** bta_av_co_video_src_data_path().
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_ci_src_data_ready(tBTA_AV_CHNL chnl);
+
+/*******************************************************************************
+**
+** Function bta_av_ci_setconfig
+**
+** Description This function must be called in response to function
+** bta_av_co_audio_setconfig() or bta_av_co_video_setconfig.
+** Parameter err_code is set to an AVDTP status value;
+** AVDT_SUCCESS if the codec configuration is ok,
+** otherwise error.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code,
+ UINT8 category, UINT8 num_seid, UINT8 *p_seid,
+ BOOLEAN recfg_needed);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AV_CI_H */
+
diff --git a/bta/include/bta_av_co.h b/bta/include/bta_av_co.h
new file mode 100644
index 0000000..862ac5e
--- /dev/null
+++ b/bta/include/bta_av_co.h
@@ -0,0 +1,392 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for advanced audio/video call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_CO_H
+#define BTA_AV_CO_H
+
+#include "l2c_api.h"
+#include "bta_av_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* TRUE to use SCMS-T content protection */
+#ifndef BTA_AV_CO_CP_SCMS_T
+#define BTA_AV_CO_CP_SCMS_T FALSE
+#endif
+
+/* the content protection IDs assigned by BT SIG */
+#define BTA_AV_CP_SCMS_T_ID 0x0002
+#define BTA_AV_CP_DTCP_ID 0x0001
+
+#define BTA_AV_CP_LOSC 2
+#define BTA_AV_CP_INFO_LEN 3
+
+#define BTA_AV_CP_SCMS_COPY_MASK 3
+#define BTA_AV_CP_SCMS_COPY_FREE 2
+#define BTA_AV_CP_SCMS_COPY_ONCE 1
+#define BTA_AV_CP_SCMS_COPY_NEVER 0
+
+#define BTA_AV_CO_DEFAULT_AUDIO_OFFSET AVDT_MEDIA_OFFSET
+
+enum
+{
+ BTA_AV_CO_ST_INIT,
+ BTA_AV_CO_ST_IN,
+ BTA_AV_CO_ST_OUT,
+ BTA_AV_CO_ST_OPEN,
+ BTA_AV_CO_ST_STREAM
+};
+
+
+/* data type for the Audio Codec Information*/
+typedef struct
+{
+ UINT16 bit_rate; /* SBC encoder bit rate in kbps */
+ UINT16 bit_rate_busy; /* SBC encoder bit rate in kbps */
+ UINT16 bit_rate_swampd;/* SBC encoder bit rate in kbps */
+ UINT8 busy_level; /* Busy level indicating the bit-rate to be used */
+ UINT8 codec_info[AVDT_CODEC_SIZE];
+ UINT8 codec_type; /* Codec type */
+} tBTA_AV_AUDIO_CODEC_INFO;
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_init
+**
+** Description This callout function is executed by AV when it is
+** started by calling BTA_AvEnable(). This function can be
+** used by the phone to initialize audio paths or for other
+** initialization purposes.
+**
+**
+** Returns Stream codec and content protection capabilities info.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info,
+ UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 index);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_disc_res
+**
+** Description This callout function is executed by AV to report the
+** number of stream end points (SEP) were found during the
+** AVDT stream discovery process.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps,
+ UINT8 num_snk, BD_ADDR addr);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_disc_res
+**
+** Description This callout function is executed by AV to report the
+** number of stream end points (SEP) were found during the
+** AVDT stream discovery process.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps,
+ UINT8 num_snk, BD_ADDR addr);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_getconfig
+**
+** Description This callout function is executed by AV to retrieve the
+** desired codec and content protection configuration for the
+** audio stream.
+**
+**
+** Returns Stream codec and content protection configuration info.
+**
+*******************************************************************************/
+BTA_API extern UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid,
+ UINT8 *p_num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_getconfig
+**
+** Description This callout function is executed by AV to retrieve the
+** desired codec and content protection configuration for the
+** video stream.
+**
+**
+** Returns Stream codec and content protection configuration info.
+**
+*******************************************************************************/
+BTA_API extern UINT8 bta_av_co_video_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid,
+ UINT8 *p_num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_setconfig
+**
+** Description This callout function is executed by AV to set the
+** codec and content protection configuration of the audio stream.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
+ UINT8 num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_setconfig
+**
+** Description This callout function is executed by AV to set the
+** codec and content protection configuration of the video stream.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
+ UINT8 num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_open
+**
+** Description This function is called by AV when the audio stream connection
+** is opened.
+** BTA-AV maintains the MTU of A2DP streams.
+** If this is the 2nd audio stream, mtu is the smaller of the 2
+** streams.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_open(tBTA_AV_HNDL hndl,
+ tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
+ UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_open
+**
+** Description This function is called by AV when the video stream connection
+** is opened.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_open(tBTA_AV_HNDL hndl,
+ tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
+ UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_close
+**
+** Description This function is called by AV when the audio stream connection
+** is closed.
+** BTA-AV maintains the MTU of A2DP streams.
+** When one stream is closed and no other audio stream is open,
+** mtu is reported as 0.
+** Otherwise, the MTU remains open is reported.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_close(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_close
+**
+** Description This function is called by AV when the video stream connection
+** is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_close(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_start
+**
+** Description This function is called by AV when the audio streaming data
+** transfer is started.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_start(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_start
+**
+** Description This function is called by AV when the video streaming data
+** transfer is started.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_start(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_stop
+**
+** Description This function is called by AV when the audio streaming data
+** transfer is stopped.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_stop(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_stop
+**
+** Description This function is called by AV when the video streaming data
+** transfer is stopped.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_stop(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_src_data_path
+**
+** Description This function is called to get the next data buffer from
+** the audio codec
+**
+** Returns NULL if data is not ready.
+** Otherwise, a GKI buffer (BT_HDR*) containing the audio data.
+**
+*******************************************************************************/
+BTA_API extern void * bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type,
+ UINT32 *p_len, UINT32 *p_timestamp);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_src_data_path
+**
+** Description This function is called to get the next data buffer from
+** the video codec.
+**
+** Returns NULL if data is not ready.
+** Otherwise, a video data buffer (UINT8*).
+**
+*******************************************************************************/
+BTA_API extern void * bta_av_co_video_src_data_path(tBTA_AV_CODEC codec_type,
+ UINT32 *p_len, UINT32 *p_timestamp);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_drop
+**
+** Description An Audio packet is dropped. .
+** It's very likely that the connected headset with this handle
+** is moved far away. The implementation may want to reduce
+** the encoder bit rate setting to reduce the packet size.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_drop(tBTA_AV_HNDL hndl);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_report_conn
+**
+** Description This function is called by AV when the reporting channel is
+** opened (open=TRUE) or closed (open=FALSE).
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_report_conn (BOOLEAN open, UINT8 avdt_handle);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_report_rr
+**
+** Description This function is called by AV when a Receiver Report is
+** received
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_report_rr (UINT32 packet_lost);
+
+/*******************************************************************************
+**
+** Function bta_av_co_audio_delay
+**
+** Description This function is called by AV when the audio stream connection
+** needs to send the initial delay report to the connected SRC.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, UINT16 delay);
+
+/*******************************************************************************
+**
+** Function bta_av_co_video_delay
+**
+** Description This function is called by AV when the video stream connection
+** needs to send the initial delay report to the connected SRC.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_delay(tBTA_AV_HNDL hndl, UINT16 delay);
+
+#endif /* BTA_AV_CO_H */
+
diff --git a/bta/include/bta_av_sbc.h b/bta/include/bta_av_sbc.h
new file mode 100644
index 0000000..98eb6ae
--- /dev/null
+++ b/bta/include/bta_av_sbc.h
@@ -0,0 +1,207 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface to utility functions for dealing with SBC data
+ * frames and codec capabilities.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_SBC_H
+#define BTA_AV_SBC_H
+
+/*****************************************************************************
+** constants
+*****************************************************************************/
+
+/* SBC packet header size */
+#define BTA_AV_SBC_HDR_SIZE A2D_SBC_MPL_HDR_LEN
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_init_up_sample
+**
+** Description initialize the up sample
+**
+** src_sps: samples per second (source audio data)
+** dst_sps: samples per second (converted audio data)
+** bits: number of bits per pcm sample
+** n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns none
+**
+*******************************************************************************/
+extern void bta_av_sbc_init_up_sample (UINT32 src_sps, UINT32 dst_sps,
+ UINT16 bits, UINT16 n_channels);
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (number of bytes)
+** dst_samples: The size of p_dst (number of bytes)
+**
+** Note: An AE reported an issue with this function.
+** When called with bta_av_sbc_up_sample(src, uint8_array_dst..)
+** the byte before uint8_array_dst may get overwritten.
+** Using uint16_array_dst avoids the problem.
+** This issue is related to endian-ness and is hard to resolve
+** in a generic manner.
+** **************** Please use uint16 array as dst.
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample_16s (16bits-stereo)
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (in uint of 4 bytes)
+** dst_samples: The size of p_dst (in uint of 4 bytes)
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample_16s (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample_16m (16bits-mono)
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (in uint of 2 bytes)
+** dst_samples: The size of p_dst (in uint of 2 bytes)
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample_8s (8bits-stereo)
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (in uint of 2 bytes)
+** dst_samples: The size of p_dst (in uint of 2 bytes)
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_up_sample_8m (8bits-mono)
+**
+** Description Given the source (p_src) audio data and
+** source speed (src_sps, samples per second),
+** This function converts it to audio data in the desired format
+**
+** p_src: the data buffer that holds the source audio data
+** p_dst: the data buffer to hold the converted audio data
+** src_samples: The number of source samples (number of bytes)
+** dst_samples: The size of p_dst (number of bytes)
+**
+** Returns The number of bytes used in p_dst
+** The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst,
+ UINT32 src_samples, UINT32 dst_samples,
+ UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_cfg_for_cap
+**
+** Description Determine the preferred SBC codec configuration for the
+** given codec capabilities. The function is passed the
+** preferred codec configuration and the peer codec
+** capabilities for the stream. The function attempts to
+** match the preferred capabilities with the configuration
+** as best it can. The resulting codec configuration is
+** returned in the same memory used for the capabilities.
+**
+** Returns 0 if ok, nonzero if error.
+** Codec configuration in p_cap.
+**
+*******************************************************************************/
+extern UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC_CIE *p_pref);
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_cfg_in_cap
+**
+** Description This function checks whether an SBC codec configuration
+** is allowable for the given codec capabilities.
+**
+** Returns 0 if ok, nonzero if error.
+**
+*******************************************************************************/
+extern UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap);
+
+/*******************************************************************************
+**
+** Function bta_av_sbc_bld_hdr
+**
+** Description This function builds the packet header for MPF1.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void bta_av_sbc_bld_hdr(BT_HDR *p_buf, UINT16 fr_per_pkt);
+
+#endif /* BTA_AV_SBC_H */
+
diff --git a/bta/include/bta_dm_ci.h b/bta/include/bta_dm_ci.h
new file mode 100644
index 0000000..bf0983e
--- /dev/null
+++ b/bta/include/bta_dm_ci.h
@@ -0,0 +1,81 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for device mananger call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_CI_H
+#define BTA_DM_CI_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_dm_ci_io_req
+**
+** Description This function must be called in response to function
+** bta_dm_co_io_req(), if *p_oob_data is set to BTA_OOB_UNKNOWN
+** by bta_dm_co_io_req().
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_ci_io_req(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+ tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function bta_dm_ci_rmt_oob
+**
+** Description This function must be called in response to function
+** bta_dm_co_rmt_oob() to provide the OOB data associated
+** with the remote device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr,
+ BT_OCTET16 c, BT_OCTET16 r);
+/*******************************************************************************
+**
+** Function bta_dm_sco_ci_data_ready
+**
+** Description This function sends an event to indicating that the phone
+** has SCO data ready..
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/bta/include/bta_dm_co.h b/bta/include/bta_dm_co.h
new file mode 100644
index 0000000..864104e
--- /dev/null
+++ b/bta/include/bta_dm_co.h
@@ -0,0 +1,274 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for device mananger callout functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_CO_H
+#define BTA_DM_CO_H
+
+#include "bta_sys.h"
+
+
+#ifndef BTA_SCO_OUT_PKT_SIZE
+ #define BTA_SCO_OUT_PKT_SIZE BTM_SCO_DATA_SIZE_MAX
+#endif
+
+#define BTA_SCO_CODEC_PCM 0 /* used for regular SCO */
+#define BTA_SCO_CODEC_SBC 1 /* used for WBS */
+typedef UINT8 tBTA_SCO_CODEC_TYPE;
+
+#define BTA_DM_SCO_SAMP_RATE_8K 8000
+#define BTA_DM_SCO_SAMP_RATE_16K 16000
+
+/* SCO codec information */
+typedef struct
+{
+ tBTA_SCO_CODEC_TYPE codec_type;
+}tBTA_CODEC_INFO;
+
+#define BTA_DM_SCO_ROUTE_PCM BTM_SCO_ROUTE_PCM
+#define BTA_DM_SCO_ROUTE_HCI BTM_SCO_ROUTE_HCI
+
+typedef tBTM_SCO_ROUTE_TYPE tBTA_DM_SCO_ROUTE_TYPE;
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_dm_co_io_req
+**
+** Description This callout function is executed by DM to get IO capabilities
+** of the local device for the Simple Pairing process
+**
+** Parameters bd_addr - The peer device
+** *p_io_cap - The local Input/Output capabilities
+** *p_oob_data - TRUE, if OOB data is available for the peer device.
+** *p_auth_req - TRUE, if MITM protection is required.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
+ tBTA_OOB_DATA *p_oob_data, tBTA_AUTH_REQ *p_auth_req,
+ BOOLEAN is_orig);
+
+/*******************************************************************************
+**
+** Function bta_dm_co_io_rsp
+**
+** Description This callout function is executed by DM to report IO capabilities
+** of the peer device for the Simple Pairing process
+**
+** Parameters bd_addr - The peer device
+** io_cap - The remote Input/Output capabilities
+** oob_data - TRUE, if OOB data is available for the peer device.
+** auth_req - TRUE, if MITM protection is required.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_io_rsp(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+ tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function bta_dm_co_lk_upgrade
+**
+** Description This callout function is executed by DM to check if the
+** platform wants allow link key upgrade
+**
+** Parameters bd_addr - The peer device
+** *p_upgrade - TRUE, if link key upgrade is desired.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_lk_upgrade(BD_ADDR bd_addr, BOOLEAN *p_upgrade );
+
+/*******************************************************************************
+**
+** Function bta_dm_co_loc_oob
+**
+** Description This callout function is executed by DM to report the OOB
+** data of the local device for the Simple Pairing process
+**
+** Parameters valid - TRUE, if the local OOB data is retrieved from LM
+** c - Simple Pairing Hash C
+** r - Simple Pairing Randomnizer R
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r);
+
+/*******************************************************************************
+**
+** Function bta_dm_co_rmt_oob
+**
+** Description This callout function is executed by DM to request the OOB
+** data for the remote device for the Simple Pairing process
+**
+** Parameters bd_addr - The peer device
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_rmt_oob(BD_ADDR bd_addr);
+
+/*****************************************************************************
+** SCO over HCI Function Declarations
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_init
+**
+** Description This function can be used by the phone to initialize audio
+** codec or for other initialization purposes before SCO connection
+** is opened.
+**
+**
+** Returns Void.
+**
+*******************************************************************************/
+BTA_API extern tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
+ tBTA_CODEC_INFO *p_codec_info, UINT8 app_id);
+
+
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_open
+**
+** Description This function is executed when a SCO connection is open.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event);
+
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_close
+**
+** Description This function is called when a SCO connection is closed
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_co_close(void);
+
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_out_data
+**
+** Description This function is called to send SCO data over HCI.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_co_out_data(BT_HDR **p_buf);
+
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_in_data
+**
+** Description This function is called to send incoming SCO data to application.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status);
+
+
+
+/*******************************************************************************
+**
+** Function bta_dm_co_ble_io_req
+**
+** Description This callout function is executed by DM to get BLE IO capabilities
+** before SMP pairing gets going.
+**
+** Parameters bd_addr - The peer device
+** *p_io_cap - The local Input/Output capabilities
+** *p_oob_data - TRUE, if OOB data is available for the peer device.
+** *p_auth_req - Auth request setting (Bonding and MITM required or not)
+** *p_max_key_size - max key size local device supported.
+** *p_init_key - initiator keys.
+** *p_resp_key - responder keys.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_ble_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
+ tBTA_OOB_DATA *p_oob_data,
+ tBTA_LE_AUTH_REQ *p_auth_req,
+ UINT8 *p_max_key_size,
+ tBTA_LE_KEY_TYPE *p_init_key,
+ tBTA_LE_KEY_TYPE *p_resp_key );
+
+
+/*******************************************************************************
+**
+** Function bta_dm_co_ble_local_key_reload
+**
+** Description This callout function is to load the local BLE keys if available
+** on the device.
+**
+** Parameters none
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_ble_load_local_keys (tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+ tBTA_BLE_LOCAL_ID_KEYS *p_id_keys);
+
+// btla-specific ++
+/*******************************************************************************
+**
+** Function bta_dm_co_ble_io_req
+**
+** Description This callout function is executed by DM to get BLE IO capabilities
+** before SMP pairing gets going.
+**
+** Parameters bd_addr - The peer device
+** *p_io_cap - The local Input/Output capabilities
+** *p_oob_data - TRUE, if OOB data is available for the peer device.
+** *p_auth_req - Auth request setting (Bonding and MITM required or not)
+** *p_max_key_size - max key size local device supported.
+** *p_init_key - initiator keys.
+** *p_resp_key - responder keys.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_ble_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
+ tBTA_OOB_DATA *p_oob_data,
+ tBTA_LE_AUTH_REQ *p_auth_req,
+ UINT8 *p_max_key_size,
+ tBTA_LE_KEY_TYPE *p_init_key,
+ tBTA_LE_KEY_TYPE *p_resp_key );
+// btla-specific --
+
+#endif
diff --git a/bta/include/bta_fs_api.h b/bta/include/bta_fs_api.h
new file mode 100644
index 0000000..a3c34e0
--- /dev/null
+++ b/bta/include/bta_fs_api.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the file system of BTA, Broadcom's
+ * Bluetooth application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_FS_API_H
+#define BTA_FS_API_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* Configuration structure */
+typedef struct
+{
+ UINT16 max_file_len; /* Maximum size file name */
+ UINT16 max_path_len; /* Maximum path length (includes appended file name) */
+ char path_separator; /* 0x2f ('/'), or 0x5c ('\') */
+} tBTA_FS_CFG;
+
+extern tBTA_FS_CFG * p_bta_fs_cfg;
+
+#endif /* BTA_FS_API_H */
diff --git a/bta/include/bta_fs_ci.h b/bta/include/bta_fs_ci.h
new file mode 100644
index 0000000..e2b5093
--- /dev/null
+++ b/bta/include/bta_fs_ci.h
@@ -0,0 +1,256 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for file system call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_FS_CI_H
+#define BTA_FS_CI_H
+
+#include "bta_fs_co.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* Open Complete Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FS_CO_STATUS status;
+ UINT32 file_size;
+ int fd;
+ const char *p_file;
+} tBTA_FS_CI_OPEN_EVT;
+
+/* Read Ready Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FS_CO_STATUS status;
+ int fd;
+ UINT16 num_read;
+} tBTA_FS_CI_READ_EVT;
+
+/* Write Ready Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FS_CO_STATUS status;
+ int fd;
+} tBTA_FS_CI_WRITE_EVT;
+
+/* Get Directory Entry Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FS_CO_STATUS status;
+} tBTA_FS_CI_GETDIR_EVT;
+
+/* Resume Information Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FS_CO_STATUS status;
+ BD_ADDR_PTR p_addr;
+ UINT8 *p_sess_info;
+ UINT32 timeout;
+ UINT32 offset;
+ UINT8 ssn;
+ UINT8 info;
+} tBTA_FS_CI_RESUME_EVT;
+
+/* Action Complete Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FS_CO_STATUS status;
+} tBTA_FS_CI_ACTION_EVT;
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_write
+**
+** Description This function sends an event to BTA indicating the phone
+** has written the number of bytes specified in the call-out
+** function, bta_fs_co_write(), and is ready for more data.
+** This function is used to control the TX data flow.
+** Note: The data buffer is released by the stack aioer
+** calling this function.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_fs_ci_open call-in function.
+** status - BTA_FS_CO_OK, BTA_FS_CO_NOSPACE, or BTA_FS_CO_FAIL
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_write(int fd, tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_read
+**
+** Description This function sends an event to BTA indicating the phone has
+** read in the requested amount of data specified in the
+** bta_fs_co_read() call-out function. It should only be called
+** when the requested number of bytes has been read in, or aioer
+** the end of the file has been detected.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_fs_ci_open call-in function.
+** num_bytes_read - number of bytes read into the buffer
+** specified in the read callout-function.
+** status - BTA_FS_CO_OK if full buffer of data,
+** BTA_FS_CO_EOF if the end of file has been reached,
+** BTA_FS_CO_FAIL if an error has occurred.
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_read(int fd, UINT16 num_bytes_read,
+ tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_open
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished opening a file for reading or writing.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_fs_ci_open call-in function.
+** status - BTA_FS_CO_OK if file was opened in mode specified
+** in the call-out function.
+** BTA_FS_CO_EACCES if the file exists, but contains
+** the wrong access permissions.
+** BTA_FS_CO_FAIL if any other error has occurred.
+** file_size - The total size of the file
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_open(int fd, tBTA_FS_CO_STATUS status,
+ UINT32 file_size, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_direntry
+**
+** Description This function is called in response to the
+** bta_fs_co_getdirentry call-out function.
+**
+** Parameters status - BTA_FS_CO_OK if p_entry points to a valid entry.
+** BTA_FS_CO_EODIR if no more entries (p_entry is ignored).
+** BTA_FS_CO_FAIL if any errors have occurred.
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_direntry(tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_resume
+**
+** Description This function is called in response to the
+** bta_fs_co_resume call-out function.
+**
+** Parameters p_sess_info - the stored session ID and related information.
+** ssn - the stored session sequence number.
+** info - the stored BTA specific information (like last active operation).
+** status - BTA_FS_CO_OK if p_entry points to a valid entry.
+** BTA_FS_CO_FAIL if any errors have occurred.
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_resume (BD_ADDR_PTR p_addr, UINT8 *p_sess_info,
+ UINT32 timeout, UINT32 offset, UINT8 ssn, UINT8 info,
+ tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_action
+**
+** Description This function is called in response to one of the action
+** call-out functions: bta_fs_co_copy, bta_fs_co_rename or
+** bta_fs_co_set_perms.
+**
+** Parameters status - BTA_FS_CO_OK if the action is succession.
+** BTA_FS_CO_FAIL if any errors have occurred.
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_action(tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function bta_fs_ci_resume_op
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished opening a file for reading or writing on resume.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_fs_ci_open call-in function.
+** status - BTA_FS_CO_OK if file was opened in mode specified
+** in the call-out function.
+** BTA_FS_CO_EACCES if the file exists, but contains
+** the wrong access permissions.
+** BTA_FS_CO_FAIL if any other error has occurred.
+** p_file - The file name associated with fd
+** file_size - The total size of the file
+** evt - Used Internally by BTA -> MUST be same value passed
+** in call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_resume_op(int fd, tBTA_FS_CO_STATUS status, const char *p_file,
+ UINT32 file_size, UINT16 evt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_FS_CI_H */
+
diff --git a/bta/include/bta_fs_co.h b/bta/include/bta_fs_co.h
new file mode 100644
index 0000000..7ab16fa
--- /dev/null
+++ b/bta/include/bta_fs_co.h
@@ -0,0 +1,703 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for the synchronization server call-out
+ * functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_FS_CO_H
+#define BTA_FS_CO_H
+
+#include <time.h>
+
+#include "bta_api.h"
+#include "goep_fs.h"
+#include "obx_api.h"
+
+/*****************************************************************************
+** Constants and Data Types
+*****************************************************************************/
+
+#ifndef BTA_FS_CO_MAX_SSN_ENTRIES
+#define BTA_FS_CO_MAX_SSN_ENTRIES 10
+#endif
+
+/* Maximum path length supported by FS_CO */
+#ifndef BTA_FS_CO_PATH_LEN
+#define BTA_FS_CO_PATH_LEN 294
+#endif
+
+#ifndef BTA_FS_CO_TEST_ROOT
+#define BTA_FS_CO_TEST_ROOT "test_files"
+#endif
+
+#define BTA_FS_CO_TEST_TYPE_NONE 0
+#define BTA_FS_CO_TEST_TYPE_REJECT 1
+#define BTA_FS_CO_TEST_TYPE_SUSPEND 2
+
+#ifndef BTA_FS_CO_TEST_AB_END
+#define BTA_FS_CO_TEST_AB_END BTA_FS_CO_TEST_TYPE_NONE
+#endif
+
+/**************************
+** Common Definitions
+***************************/
+
+/* Status codes returned by call-out functions, or in call-in functions as status */
+#define BTA_FS_CO_OK GOEP_OK
+#define BTA_FS_CO_FAIL GOEP_FAIL /* Used to pass all other errors */
+#define BTA_FS_CO_EACCES GOEP_EACCES
+#define BTA_FS_CO_ENOTEMPTY GOEP_ENOTEMPTY
+#define BTA_FS_CO_EOF GOEP_EOF
+#define BTA_FS_CO_EODIR GOEP_EODIR
+#define BTA_FS_CO_ENOSPACE GOEP_ENOSPACE/* Returned in bta_fs_ci_open if no room */
+#define BTA_FS_CO_EIS_DIR GOEP_EIS_DIR
+#define BTA_FS_CO_RESUME GOEP_RESUME /* used in ci_open, on resume */
+#define BTA_FS_CO_NONE GOEP_NONE /* used in ci_open, on resume (no file to resume) */
+
+typedef UINT16 tBTA_FS_CO_STATUS;
+
+/* the index to the permission flags */
+#define BTA_FS_PERM_USER 0
+#define BTA_FS_PERM_GROUP 1
+#define BTA_FS_PERM_OTHER 2
+/* max number of the permission flags */
+#define BTA_FS_PERM_SIZE 3
+
+/* Flags passed to the open function (bta_fs_co_open)
+** Values are OR'd together. (First 3 are
+** mutually exclusive.
+*/
+#define BTA_FS_O_RDONLY GOEP_O_RDONLY
+#define BTA_FS_O_WRONLY GOEP_O_WRONLY
+#define BTA_FS_O_RDWR GOEP_O_RDWR
+
+#define BTA_FS_O_CREAT GOEP_O_CREAT
+#define BTA_FS_O_EXCL GOEP_O_EXCL
+#define BTA_FS_O_TRUNC GOEP_O_TRUNC
+
+#define BTA_FS_O_MODE_MASK(x) (((UINT16)(x)) & 0x0003)
+
+/* Origin for the bta_fs_co_seek function */
+#define BTA_FS_SEEK_SET GOEP_SEEK_SET
+#define BTA_FS_SEEK_CUR GOEP_SEEK_CUR
+#define BTA_FS_SEEK_END GOEP_SEEK_END
+
+/* mode field in bta_fs_co_access callout */
+#define BTA_FS_ACC_EXIST GOEP_ACC_EXIST
+#define BTA_FS_ACC_READ GOEP_ACC_READ
+#define BTA_FS_ACC_RDWR GOEP_ACC_RDWR
+
+#define BTA_FS_LEN_UNKNOWN GOEP_LEN_UNKNOWN
+#define BTA_FS_INVALID_FD GOEP_INVALID_FD
+#define BTA_FS_INVALID_APP_ID (0xFF) /* this app_id is reserved */
+
+/* mode field in tBTA_FS_DIRENTRY (OR'd together) */
+#define BTA_FS_A_RDONLY GOEP_A_RDONLY
+#define BTA_FS_A_DIR GOEP_A_DIR /* Entry is a sub directory */
+
+#define BTA_FS_CTIME_LEN GOEP_CTIME_LEN /* Creation time "yyyymmddTHHMMSSZ" */
+
+/* Return structure type for a directory entry */
+typedef struct
+{
+ UINT32 refdata; /* holder for OS specific data used to get next entry */
+ UINT32 filesize;
+ char crtime[BTA_FS_CTIME_LEN]; /* "yyyymmddTHHMMSSZ", or "" if none */
+ char *p_name; /* Contains the addr of memory to copy name into */
+ UINT8 mode; /* BTA_FS_A_RDONLY and/or BTA_FS_A_DIR */
+} tBTA_FS_DIRENTRY;
+
+/* session state */
+enum
+{
+ BTA_FS_CO_SESS_ST_NONE,
+ BTA_FS_CO_SESS_ST_ACTIVE,
+ BTA_FS_CO_SESS_ST_SUSPEND,
+ BTA_FS_CO_SESS_ST_RESUMING
+};
+typedef UINT8 tBTA_FS_CO_SESS_ST;
+
+
+
+/* a data type to keep an array of ssn/file offset - the info can be saved to NV */
+typedef struct
+{
+ char path[BTA_FS_CO_PATH_LEN + 1]; /* the "current path". path[0]==0-> root */
+ char file[BTA_FS_CO_PATH_LEN + 1]; /* file[0] !=0 on resume -> the previous suspended session had opened files */
+ int oflags; /* the flag to open the file */
+ BD_ADDR bd_addr;
+ UINT8 sess_info[OBX_SESSION_INFO_SIZE];
+ UINT32 offset; /* last file offset */
+ UINT32 timeout; /* the timeout value on suspend */
+ time_t suspend_time; /* the time of suspend */
+ UINT16 nbytes; /* number of bytes for last read/write */
+ UINT8 ssn;
+ UINT8 info; /* info for BTA on the client side */
+ UINT8 app_id;
+ tBTA_FS_CO_SESS_ST sess_st;
+} tBTA_FS_CO_SESSION;
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+/**************************
+** Common Functions
+***************************/
+/*******************************************************************************
+**
+** Function bta_fs_co_init
+**
+** Description This function is executed as a part of the start up sequence
+** to make sure the control block is initialized.
+**
+** Parameters void.
+**
+** Returns void
+**
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_init(void);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_open
+**
+** Description This function is executed by BTA when a file is opened.
+** The phone uses this function to open
+** a file for reading or writing.
+**
+** Parameters p_path - Fully qualified path and file name.
+** oflags - permissions and mode (see constants above)
+** size - size of file to put (0 if unavailable or not applicable)
+** evt - event that must be passed into the call-in function.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, a file descriptor (int),
+** if successful, and an error code (tBTA_FS_CO_STATUS)
+** are returned in the call-in function, bta_fs_ci_open().
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_open(const char *p_path, int oflags, UINT32 size,
+ UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_session_info
+**
+** Description This function is executed by BTA when a reliable session is
+** established (p_sess_info != NULL) or ended (p_sess_info == NULL).
+**
+** Parameters bd_addr - the peer address
+** p_sess_info - the session ID and related information.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_session_info(BD_ADDR bd_addr, UINT8 *p_sess_info, UINT8 ssn,
+ tBTA_FS_CO_SESS_ST new_st, char *p_path, UINT8 *p_info, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_resume_op
+**
+** Description This function is executed by BTA when a reliable session is
+** resumed and there was an interrupted operation.
+**
+** Parameters offset - the session ID and related information.
+** evt - event that must be passed into the call-in function.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_resume_op(UINT32 offset, UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_suspend
+**
+** Description This function is executed by BTA when a reliable session is
+** suspended.
+**
+** Parameters bd_addr - the peer address
+** ssn - the session sequence number.
+** info - the BTA specific information (like last active operation).
+** p_offset- the location to receive object offset of the suspended session
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_suspend(BD_ADDR bd_addr, UINT8 *p_sess_info, UINT8 ssn,
+ UINT32 *p_timeout, UINT32 *p_offset, UINT8 info, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_resume
+**
+** Description This function is executed by BTA when resuming a session.
+** This is used to retrieve the session ID and related information
+**
+** Parameters evt - event that must be passed into the call-in function.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, the related session information,
+** if successful, and an error code (tBTA_FS_CO_STATUS)
+** are returned in the call-in function, bta_fs_ci_resume().
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_resume(UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_sess_ssn
+**
+** Description This function is executed by BTA when resuming a session.
+** This is used to inform call-out module if the ssn/file offset
+** needs to be adjusted.
+**
+** Parameters ssn - the session sequence number of the first request
+** after resume.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_sess_ssn(int fd, UINT8 ssn, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_setdir
+**
+** Description This function is executed by BTA when the server changes the
+** local path
+**
+** Parameters p_path - the new path.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_setdir(const char *p_path, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_close
+**
+** Description This function is called by BTA when a connection to a
+** client is closed.
+**
+** Parameters fd - file descriptor of file to close.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns (tBTA_FS_CO_STATUS) status of the call.
+** [BTA_FS_CO_OK if successful],
+** [BTA_FS_CO_FAIL if failed ]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_close(int fd, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_read
+**
+** Description This function is called by BTA to read in data from the
+** previously opened file on the phone.
+**
+** Parameters fd - file descriptor of file to read from.
+** p_buf - buffer to read the data into.
+** nbytes - number of bytes to read into the buffer.
+** evt - event that must be passed into the call-in function.
+** ssn - session sequence number. Ignored, if bta_fs_co_open
+** was not called with BTA_FS_CO_RELIABLE.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, bta_fs_ci_read() is
+** called with the buffer of data, along with the number
+** of bytes read into the buffer, and a status. The
+** call-in function should only be called when ALL requested
+** bytes have been read, the end of file has been detected,
+** or an error has occurred.
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_read(int fd, UINT8 *p_buf, UINT16 nbytes, UINT16 evt,
+ UINT8 ssn, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_write
+**
+** Description This function is called by io to send file data to the
+** phone.
+**
+** Parameters fd - file descriptor of file to write to.
+** p_buf - buffer to read the data from.
+** nbytes - number of bytes to write out to the file.
+** evt - event that must be passed into the call-in function.
+** ssn - session sequence number. Ignored, if bta_fs_co_open
+** was not called with BTA_FS_CO_RELIABLE.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, bta_fs_ci_write() is
+** called with the file descriptor and the status. The
+** call-in function should only be called when ALL requested
+** bytes have been written, or an error has been detected,
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_write(int fd, const UINT8 *p_buf, UINT16 nbytes, UINT16 evt,
+ UINT8 ssn, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_seek
+**
+** Description This function is called by io to move the file pointer
+** of a previously opened file to the specified location for
+** the next read or write operation.
+**
+** Parameters fd - file descriptor of file.
+** offset - Number of bytes from origin.
+** origin - Initial position: BTA_FS_SEEK_SET, BTA_FS_SEEK_CUR,
+** or BTA_FS_SEEK_END.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_seek (int fd, INT32 offset, INT16 origin, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_access
+**
+** Description This function is called to check the existence of a file or
+** directory.
+**
+** Parameters p_path - (input) file or directory to access (fully qualified path).
+** mode - (input) [BTA_FS_ACC_EXIST, BTA_FS_ACC_READ, or BTA_FS_ACC_RDWR]
+** p_is_dir - (output) returns TRUE if p_path specifies a directory.
+** app_id - (input) application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns (tBTA_FS_CO_STATUS) status of the call.
+** [BTA_FS_CO_OK if it exists]
+** [BTA_FS_CO_EACCES if permissions are wrong]
+** [BTA_FS_CO_FAIL if it does not exist]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_access(const char *p_path, int mode,
+ BOOLEAN *p_is_dir, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_mkdir
+**
+** Description This function is called to create a directory with
+** the pathname given by path. The pathname is a null terminated
+** string. All components of the path must already exist.
+**
+** Parameters p_path - (input) name of directory to create (fully qualified path).
+** app_id - (input) application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns (tBTA_FS_CO_STATUS) status of the call.
+** [BTA_FS_CO_OK if successful]
+** [BTA_FS_CO_FAIL if unsuccessful]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_mkdir(const char *p_path, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_rmdir
+**
+** Description This function is called to remove a directory whose
+** name is given by path. The directory must be empty.
+**
+** Parameters p_path - (input) name of directory to remove (fully qualified path).
+** app_id - (input) application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns (tBTA_FS_CO_STATUS) status of the call.
+** [BTA_FS_CO_OK if successful]
+** [BTA_FS_CO_EACCES if read-only]
+** [BTA_FS_CO_ENOTEMPTY if directory is not empty]
+** [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_rmdir(const char *p_path, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_unlink
+**
+** Description This function is called by to remove a file whose name
+** is given by p_path.
+**
+** Parameters p_path - (input) name of file to remove (fully qualified path).
+** app_id - (input) application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns (tBTA_FS_CO_STATUS) status of the call.
+** [BTA_FS_CO_OK if successful]
+** [BTA_FS_CO_EACCES if read-only]
+** [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_unlink(const char *p_path, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_getdirentry
+**
+** Description This function is called to retrieve a directory entry for the
+** specified path. The first/next directory should be filled
+** into the location specified by p_entry.
+**
+** Parameters p_path - directory to search (Fully qualified path)
+** first_item - TRUE if first search, FALSE if next search
+** (p_cur contains previous)
+** p_entry (input/output) - Points to last entry data (valid when
+** first_item is FALSE)
+** evt - event that must be passed into the call-in function.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, the status is passed
+** in the bta_fs_ci_direntry() call-in function.
+** BTA_FS_CO_OK is returned when p_entry is valid,
+** BTA_FS_CO_EODIR is returned when no more entries [finished]
+** BTA_FS_CO_FAIL is returned if an error occurred
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_getdirentry(const char *p_path, BOOLEAN first_item,
+ tBTA_FS_DIRENTRY *p_entry, UINT16 evt,
+ UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_copy
+**
+** Description This function is called to copy a file/directory whose
+** name is given by p_src_path to p_dest_path.
+**
+** Parameters p_src_path - (input) name of file/directory to be copied (fully qualified path).
+** p_dest_path - (input) new name of file/directory(fully qualified path).
+** p_perms - the permission of the new object.
+** evt - event that must be passed into the call-in function.
+** app_id - (input) application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns (tBTA_FS_CO_STATUS) status of the call.
+** [BTA_FS_CO_OK if successful]
+** [BTA_FS_CO_EIS_DIR if p_src_path is a folder]
+** [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
+** or p_src_path is a directory and p_dest_path specifies a different path. ]
+** [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_copy(const char *p_src_path, const char *p_dest_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_rename
+**
+** Description This function is called to move a file/directory whose
+** name is given by p_src_path to p_dest_path.
+**
+** Parameters p_src_path - (input) name of file/directory to be moved (fully qualified path).
+** p_dest_path - (input) new name of file/directory(fully qualified path).
+** p_perms - the permission of the new object.
+** app_id - (input) application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns (tBTA_FS_CO_STATUS) status of the call.
+** [BTA_FS_CO_OK if successful]
+** [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
+** or p_src_path is a directory and p_dest_path specifies a different path. ]
+** [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_rename(const char *p_src_path, const char *p_dest_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_set_perms
+**
+** Description This function is called to set the permission a file/directory
+** with name as p_src_path.
+**
+** Parameters p_src_path - (input) name of file/directory to set permission (fully qualified path).
+** p_perms - the permission .
+** app_id - (input) application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns (tBTA_FS_CO_STATUS) status of the call.
+** [BTA_FS_CO_OK if successful]
+** [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
+** or p_src_path is a directory and p_dest_path specifies a different path. ]
+** [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_set_perms(const char *p_src_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_sess_fopen
+**
+** Description This function is called by bta_fs_co_open to keep track of
+** the opened file (for reliable session suspend/resume.)
+**
+** Parameters p_path - Fully qualified path and file name.
+** oflags - permissions and mode (see constants above)
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_sess_fopen(const char *p_path, int oflags, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_sess_fclose
+**
+** Description This function is called by bta_fs_co_close
+**
+** Parameters app_id - application ID specified in the enable functions.
+** It can be used to identify which profile is the caller
+** of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_sess_fclose(UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_sess_offset
+**
+** Description This function is called by bta_fs_co_write to keep track of
+** the last file offset (Only the receiving side needs to keep
+** track of the file offset)
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_sess_offset(UINT8 ssn, INT32 pos, UINT16 nbytes, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_suspended_addr
+**
+** Description find the peer address of the suspended session control block
+** for the given an app_id.
+**
+** Returns the control block found.
+**
+*******************************************************************************/
+BTA_API extern UINT8 *bta_fs_co_suspended_addr(UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_num_suspended_session
+**
+** Description find the number of suspended session control blocks for the
+** given an app_id.
+**
+** Returns the number of control blocks found.
+**
+*******************************************************************************/
+BTA_API extern UINT8 bta_fs_co_num_suspended_session(UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_get_active_session
+**
+** Description find the active session control block for the given an app_id.
+**
+** Returns the control block found.
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_SESSION *bta_fs_co_get_active_session(UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_fs_co_init_db
+**
+** Description Initialize the session control blocks for platform.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_init_db (tBTA_FS_CO_SESSION *p_first);
+
+/*******************************************************************************
+**
+** Function bta_fs_convert_oflags
+**
+** Description This function converts the open flags from BTA into MFS.
+**
+** Returns BTA FS status value.
+**
+*******************************************************************************/
+BTA_API extern int bta_fs_convert_bta_oflags(int bta_oflags);
+
+#endif /* BTA_FS_CO_H */
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
new file mode 100644
index 0000000..0404847
--- /dev/null
+++ b/bta/include/bta_gatt_api.h
@@ -0,0 +1,1219 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for BTA GATT.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATT_API_H
+#define BTA_GATT_API_H
+
+#include "bta_api.h"
+#include "gatt_api.h"
+
+#ifndef BTA_GATT_INCLUDED
+#define BTA_GATT_INCLUDED FALSE
+#endif
+
+
+#if ((BLE_INCLUDED == FALSE) && (BTA_GATT_INCLUDED == TRUE))
+#undef BTA_GATT_INCLUDED
+#define BTA_GATT_INCLUDED FALSE
+#endif
+
+
+#ifndef BTA_GATT_DEBUG
+#define BTA_GATT_DEBUG FALSE
+#endif
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+/**************************
+** Common Definitions
+***************************/
+/* GATT ID */
+typedef struct
+{
+ tBT_UUID uuid; /* uuid of the attribute */
+ UINT8 inst_id; /* instance ID */
+} tBTA_GATT_ID;
+
+/* Success code and error codes */
+#define BTA_GATT_OK GATT_SUCCESS
+#define BTA_GATT_INVALID_HANDLE GATT_INVALID_HANDLE /* 0x0001 */
+#define BTA_GATT_READ_NOT_PERMIT GATT_READ_NOT_PERMIT /* 0x0002 */
+#define BTA_GATT_WRITE_NOT_PERMIT GATT_WRITE_NOT_PERMIT /* 0x0003 */
+#define BTA_GATT_INVALID_PDU GATT_INVALID_PDU /* 0x0004 */
+#define BTA_GATT_INSUF_AUTHENTICATION GATT_INSUF_AUTHENTICATION /* 0x0005 */
+#define BTA_GATT_REQ_NOT_SUPPORTED GATT_REQ_NOT_SUPPORTED /* 0x0006 */
+#define BTA_GATT_INVALID_OFFSET GATT_INVALID_OFFSET /* 0x0007 */
+#define BTA_GATT_INSUF_AUTHORIZATION GATT_INSUF_AUTHORIZATION /* 0x0008 */
+#define BTA_GATT_PREPARE_Q_FULL GATT_PREPARE_Q_FULL /* 0x0009 */
+#define BTA_GATT_NOT_FOUND GATT_NOT_FOUND /* 0x000a */
+#define BTA_GATT_NOT_LONG GATT_NOT_LONG /* 0x000b */
+#define BTA_GATT_INSUF_KEY_SIZE GATT_INSUF_KEY_SIZE /* 0x000c */
+#define BTA_GATT_INVALID_ATTR_LEN GATT_INVALID_ATTR_LEN /* 0x000d */
+#define BTA_GATT_ERR_UNLIKELY GATT_ERR_UNLIKELY /* 0x000e */
+#define BTA_GATT_INSUF_ENCRYPTION GATT_INSUF_ENCRYPTION /* 0x000f */
+#define BTA_GATT_UNSUPPORT_GRP_TYPE GATT_UNSUPPORT_GRP_TYPE /* 0x0010 */
+#define BTA_GATT_INSUF_RESOURCE GATT_INSUF_RESOURCE /* 0x0011 */
+
+
+#define BTA_GATT_ILLEGAL_PARAMETER GATT_ILLEGAL_PARAMETER /* 0x0087 */
+#define BTA_GATT_NO_RESOURCES GATT_NO_RESOURCES /* 0x0080 */
+#define BTA_GATT_INTERNAL_ERROR GATT_INTERNAL_ERROR /* 0x0081 */
+#define BTA_GATT_WRONG_STATE GATT_WRONG_STATE /* 0x0082 */
+#define BTA_GATT_DB_FULL GATT_DB_FULL /* 0x0083 */
+#define BTA_GATT_BUSY GATT_BUSY /* 0x0084 */
+#define BTA_GATT_ERROR GATT_ERROR /* 0x0085 */
+#define BTA_GATT_CMD_STARTED GATT_CMD_STARTED /* 0x0086 */
+#define BTA_GATT_PENDING GATT_PENDING /* 0x0088 */
+#define BTA_GATT_AUTH_FAIL GATT_AUTH_FAIL /* 0x0089 */
+#define BTA_GATT_MORE GATT_MORE /* 0x008a */
+#define BTA_GATT_INVALID_CFG GATT_INVALID_CFG /* 0x008b */
+#define BTA_GATT_DUP_REG 0x008c
+#define BTA_GATT_ALREADY_OPEN 0x008d /* 0x008d */
+typedef UINT8 tBTA_GATT_STATUS;
+
+#define BTA_GATT_INVALID_CONN_ID GATT_INVALID_CONN_ID
+
+
+/* Client callback function events */
+#define BTA_GATTC_REG_EVT 0 /* GATT client is registered. */
+#define BTA_GATTC_DEREG_EVT 1 /* GATT client deregistered event */
+#define BTA_GATTC_OPEN_EVT 2 /* GATTC open request status event */
+#define BTA_GATTC_READ_CHAR_EVT 3 /* GATT read characteristic event */
+#define BTA_GATTC_WRITE_CHAR_EVT 4 /* GATT write characteristic or char descriptor event */
+#define BTA_GATTC_CLOSE_EVT 5 /* GATTC close request status event */
+#define BTA_GATTC_SEARCH_CMPL_EVT 6 /* GATT discovery complete event */
+#define BTA_GATTC_SEARCH_RES_EVT 7 /* GATT discovery result event */
+#define BTA_GATTC_READ_DESCR_EVT 8 /* GATT read characterisitc descriptor event */
+#define BTA_GATTC_WRITE_DESCR_EVT 9 /* GATT write characteristic descriptor event */
+#define BTA_GATTC_NOTIF_EVT 10 /* GATT attribute notification event */
+#define BTA_GATTC_PREP_WRITE_EVT 11 /* GATT prepare write event */
+#define BTA_GATTC_EXEC_EVT 12 /* execute write complete event */
+#define BTA_GATTC_ACL_EVT 13 /* ACL up event */
+#define BTA_GATTC_CANCEL_OPEN_EVT 14 /* cancel open event */
+#define BTA_GATTC_SRVC_CHG_EVT 15 /* service change event */
+typedef UINT8 tBTA_GATTC_EVT;
+
+typedef tGATT_IF tBTA_GATTC_IF;
+
+typedef struct
+{
+ UINT16 unit; /* as UUIUD defined by SIG */
+ UINT16 descr; /* as UUID as defined by SIG */
+ tGATT_FORMAT format;
+ INT8 exp;
+ UINT8 name_spc; /* The name space of the description */
+}tBTA_GATT_CHAR_PRES;
+
+#define BTA_GATT_CLT_CONFIG_NONE GATT_CLT_CONFIG_NONE /* 0x0000 */
+#define BTA_GATT_CLT_CONFIG_NOTIFICATION GATT_CLT_CONFIG_NOTIFICATION /* 0x0001 */
+#define BTA_GATT_CLT_CONFIG_INDICATION GATT_CLT_CONFIG_INDICATION /* 0x0002 */
+typedef UINT16 tBTA_GATT_CLT_CHAR_CONFIG;
+
+/* characteristic descriptor: server configuration value
+*/
+#define BTA_GATT_SVR_CONFIG_NONE GATT_SVR_CONFIG_NONE /* 0x0000 */
+#define BTA_GATT_SVR_CONFIG_BROADCAST GATT_SVR_CONFIG_BROADCAST /* 0x0001 */
+typedef UINT16 tBTA_GATT_SVR_CHAR_CONFIG;
+
+/* Characteristic Aggregate Format attribute value
+*/
+#define BTA_GATT_AGGR_HANDLE_NUM_MAX 10
+typedef struct
+{
+ UINT8 num_handle;
+ UINT16 handle_list[BTA_GATT_AGGR_HANDLE_NUM_MAX];
+} tBTA_GATT_CHAR_AGGRE;
+typedef tGATT_VALID_RANGE tBTA_GATT_VALID_RANGE;
+
+typedef struct
+{
+ UINT16 len;
+ UINT8 *p_value;
+}tBTA_GATT_UNFMT;
+
+#define BTA_GATT_MAX_ATTR_LEN GATT_MAX_ATTR_LEN
+
+#define BTA_GATTC_TYPE_WRITE GATT_WRITE
+#define BTA_GATTC_TYPE_WRITE_NO_RSP GATT_WRITE_NO_RSP
+typedef UINT8 tBTA_GATTC_WRITE_TYPE;
+
+#define BTA_GATT_CONN_UNKNOWN 0
+#define BTA_GATT_CONN_NO_RESOURCES GATT_CONN_NO_RESOURCES /* connection fail for l2cap resource failure */
+#define BTA_GATT_CONN_TIMEOUT GATT_CONN_TIMEOUT /* 0x08 connection timeout */
+#define BTA_GATT_CONN_TERMINATE_PEER_USER GATT_CONN_TERMINATE_PEER_USER /* 0x13 connection terminate by peer user */
+#define BTA_GATT_CONN_TERMINATE_LOCAL_HOST GATT_CONN_TERMINATE_LOCAL_HOST/* 0x16 connectionterminated by local host */
+#define BTA_GATT_CONN_FAIL_ESTABLISH GATT_CONN_FAIL_ESTABLISH /* 0x03E connection fail to establish */
+#define BTA_GATT_CONN_LMP_TIMEOUT GATT_CONN_LMP_TIMEOUT /* 0x22 connection fail for LMP response tout */
+#define BTA_GATT_CONN_CANCEL GATT_CONN_CANCEL /* 0x0100 L2CAP connection cancelled */
+#define BTA_GATT_CONN_NONE 0x0101 /* 0x0101 no connection to cancel */
+typedef UINT16 tBTA_GATT_REASON;
+
+typedef struct
+{
+ tBTA_GATT_ID id;
+ BOOLEAN is_primary;
+}tBTA_GATT_SRVC_ID;
+
+typedef struct
+{
+ tBTA_GATT_SRVC_ID srvc_id;
+ tBTA_GATT_ID char_id;
+}tBTA_GATTC_CHAR_ID;
+
+typedef struct
+{
+ tBTA_GATTC_CHAR_ID char_id;
+ tBT_UUID descr_type;
+}tBTA_GATTC_CHAR_DESCR_ID;
+
+typedef struct
+{
+ tBTA_GATT_SRVC_ID srvc_id;
+ tBTA_GATT_SRVC_ID incl_svc_id;
+}tBTA_GATTC_INCL_SVC_ID;
+
+#define BTA_GATT_TYPE_CHAR 0
+#define BTA_GATT_TYPE_CHAR_DESCR 1
+typedef UINT8 tBTA_GATT_ID_TYPE;
+
+typedef struct
+{
+ tBTA_GATT_ID_TYPE id_type;
+ union
+ {
+ tBTA_GATTC_CHAR_ID char_id;
+ tBTA_GATTC_CHAR_DESCR_ID char_descr_id;
+
+ } id_value;
+}tBTA_GATTC_ATTR_ID;
+
+#define BTA_GATTC_MULTI_MAX GATT_MAX_READ_MULTI_HANDLES
+
+typedef struct
+{
+ UINT8 num_attr;
+ tBTA_GATTC_ATTR_ID id_list[BTA_GATTC_MULTI_MAX];
+
+}tBTA_GATTC_MULTI;
+
+#define BTA_GATT_AUTH_REQ_NONE GATT_AUTH_REQ_NONE
+#define BTA_GATT_AUTH_REQ_NO_MITM GATT_AUTH_REQ_NO_MITM /* unauthenticated encryption */
+#define BTA_GATT_AUTH_REQ_MITM GATT_AUTH_REQ_MITM /* authenticated encryption */
+#define BTA_GATT_AUTH_REQ_SIGNED_NO_MITM GATT_AUTH_REQ_SIGNED_NO_MITM
+#define BTA_GATT_AUTH_REQ_SIGNED_MITM GATT_AUTH_REQ_SIGNED_MITM
+
+typedef tGATT_AUTH_REQ tBTA_GATT_AUTH_REQ;
+
+enum
+{
+ BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+ BTA_GATTC_ATTR_TYPE_CHAR,
+ BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+ BTA_GATTC_ATTR_TYPE_SRVC
+};
+typedef UINT8 tBTA_GATTC_ATTR_TYPE;
+
+
+typedef struct
+{
+ tBT_UUID uuid;
+ UINT16 s_handle;
+ UINT16 e_handle; /* used for service only */
+ UINT8 attr_type;
+ UINT8 id;
+ UINT8 prop; /* used when attribute type is characteristic */
+ BOOLEAN is_primary; /* used when attribute type is service */
+}tBTA_GATTC_NV_ATTR;
+
+/* callback data structure */
+typedef struct
+{
+ tBTA_GATT_STATUS status;
+ tBTA_GATTC_IF client_if;
+// btla-specific ++
+ tBT_UUID app_uuid;
+// btla-specific --
+}tBTA_GATTC_REG;
+
+typedef struct
+{
+ UINT8 num_pres_fmt; /* number of presentation format aggregated*/
+ tBTA_GATTC_CHAR_DESCR_ID pre_format[BTA_GATTC_MULTI_MAX];
+}tBTA_GATT_CHAR_AGGRE_VALUE;
+
+typedef union
+{
+ tBTA_GATT_CHAR_AGGRE_VALUE aggre_value;
+ tBTA_GATT_UNFMT unformat;
+
+}tBTA_GATT_READ_VAL;
+
+typedef struct
+{
+ UINT16 conn_id;
+ tBTA_GATT_STATUS status;
+ tBTA_GATT_SRVC_ID srvc_id;
+ tBTA_GATT_ID char_id;
+ tBT_UUID descr_type;
+ tBTA_GATT_READ_VAL *p_value;
+}tBTA_GATTC_READ;
+
+typedef struct
+{
+ UINT16 conn_id;
+ tBTA_GATT_STATUS status;
+ tBTA_GATT_SRVC_ID srvc_id;
+ tBTA_GATT_ID char_id;
+ tBT_UUID descr_type;
+}tBTA_GATTC_WRITE;
+
+typedef struct
+{
+ UINT16 conn_id;
+ tBTA_GATT_STATUS status;
+}tBTA_GATTC_EXEC_CMPL;
+
+typedef struct
+{
+ UINT16 conn_id;
+ tBTA_GATT_STATUS status;
+}tBTA_GATTC_SEARCH_CMPL;
+
+typedef struct
+{
+ UINT16 conn_id;
+ tBTA_GATT_SRVC_ID service_uuid;
+}tBTA_GATTC_SRVC_RES;
+
+
+typedef struct
+{
+ tBTA_GATT_STATUS status;
+ UINT16 conn_id;
+ tBTA_GATTC_IF client_if;
+ BD_ADDR remote_bda;
+}tBTA_GATTC_OPEN;
+
+typedef struct
+{
+ tBTA_GATT_STATUS status;
+ UINT16 conn_id;
+ tBTA_GATTC_IF client_if;
+ BD_ADDR remote_bda;
+ tBTA_GATT_REASON reason; /* disconnect reason code, not useful when connect event is reported */
+}tBTA_GATTC_CLOSE;
+
+typedef struct
+{
+ UINT16 conn_id;
+ BD_ADDR bda;
+ tBTA_GATTC_CHAR_ID char_id;
+ tBT_UUID descr_type;
+ UINT16 len;
+ UINT8 value[BTA_GATT_MAX_ATTR_LEN];
+ BOOLEAN is_notify;
+}tBTA_GATTC_NOTIFY;
+
+// btla-specific ++
+typedef struct
+{
+ tBTA_GATT_STATUS status;
+ tBTA_GATTC_IF client_if;
+ UINT16 conn_id;
+ BD_ADDR remote_bda;
+}tBTA_GATTC_OPEN_CLOSE;
+// btla-specific --
+
+typedef union
+{
+ tBTA_GATT_STATUS status;
+
+ tBTA_GATTC_SEARCH_CMPL search_cmpl; /* discovery complete */
+ tBTA_GATTC_SRVC_RES srvc_res; /* discovery result */
+ tBTA_GATTC_REG reg_oper; /* registration data */
+ tBTA_GATTC_OPEN open;
+ tBTA_GATTC_CLOSE close;
+ tBTA_GATTC_READ read; /* read attribute/descriptor data */
+ tBTA_GATTC_WRITE write; /* write complete data */
+ tBTA_GATTC_EXEC_CMPL exec_cmpl; /* execute complete */
+ tBTA_GATTC_NOTIFY notify; /* notification/indication event data */
+ BD_ADDR remote_bda; /* service change event */
+} tBTA_GATTC;
+
+/* Client callback function */
+typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
+
+
+/* GATT Server Data Structure */
+/* Server callback function events */
+#define BTA_GATTS_REG_EVT 0
+#define BTA_GATTS_READ_EVT GATTS_REQ_TYPE_READ /* 1 */
+#define BTA_GATTS_WRITE_EVT GATTS_REQ_TYPE_WRITE /* 2 */
+#define BTA_GATTS_EXEC_WRITE_EVT GATTS_REQ_TYPE_WRITE_EXEC /* 3 */
+#define BTA_GATTS_MTU_EVT GATTS_REQ_TYPE_MTU /* 4 */
+#define BTA_GATTS_CONF_EVT GATTS_REQ_TYPE_CONF /* 5 */
+#define BTA_GATTS_DEREG_EVT 6
+#define BTA_GATTS_CREATE_EVT 7
+#define BTA_GATTS_ADD_INCL_SRVC_EVT 8
+#define BTA_GATTS_ADD_CHAR_EVT 9
+#define BTA_GATTS_ADD_CHAR_DESCR_EVT 10
+#define BTA_GATTS_DELELTE_EVT 11
+#define BTA_GATTS_START_EVT 12
+#define BTA_GATTS_STOP_EVT 13
+#define BTA_GATTS_CONNECT_EVT 14
+#define BTA_GATTS_DISCONNECT_EVT 15
+#define BTA_GATTS_OPEN_EVT 16
+#define BTA_GATTS_CANCEL_OPEN_EVT 17
+#define BTA_GATTS_CLOSE_EVT 18
+
+typedef UINT8 tBTA_GATTS_EVT;
+typedef tGATT_IF tBTA_GATTS_IF;
+
+/* Attribute permissions
+*/
+#define BTA_GATT_PERM_READ GATT_PERM_READ /* bit 0 - 0x0001 */
+#define BTA_GATT_PERM_READ_ENCRYPTED GATT_PERM_READ_ENCRYPTED /* bit 1 - 0x0002 */
+#define BTA_GATT_PERM_READ_ENC_MITM GATT_PERM_READ_ENC_MITM /* bit 2 - 0x0004 */
+#define BTA_GATT_PERM_WRITE GATT_PERM_WRITE /* bit 4 - 0x0010 */
+#define BTA_GATT_PERM_WRITE_ENCRYPTED GATT_PERM_WRITE_ENCRYPTED /* bit 5 - 0x0020 */
+#define BTA_GATT_PERM_WRITE_ENC_MITM GATT_PERM_WRITE_ENC_MITM /* bit 6 - 0x0040 */
+#define BTA_GATT_PERM_WRITE_SIGNED GATT_PERM_WRITE_SIGNED /* bit 7 - 0x0080 */
+#define BTA_GATT_PERM_WRITE_SIGNED_MITM GATT_PERM_WRITE_SIGNED_MITM /* bit 8 - 0x0100 */
+typedef UINT16 tBTA_GATT_PERM;
+
+#define BTA_GATTS_INVALID_APP 0xff
+
+#define BTA_GATTS_INVALID_IF 0
+
+/* definition of characteristic properties */
+#define BTA_GATT_CHAR_PROP_BIT_BROADCAST GATT_CHAR_PROP_BIT_BROADCAST /* 0x01 */
+#define BTA_GATT_CHAR_PROP_BIT_READ GATT_CHAR_PROP_BIT_READ /* 0x02 */
+#define BTA_GATT_CHAR_PROP_BIT_WRITE_NR GATT_CHAR_PROP_BIT_WRITE_NR /* 0x04 */
+#define BTA_GATT_CHAR_PROP_BIT_WRITE GATT_CHAR_PROP_BIT_WRITE /* 0x08 */
+#define BTA_GATT_CHAR_PROP_BIT_NOTIFY GATT_CHAR_PROP_BIT_NOTIFY /* 0x10 */
+#define BTA_GATT_CHAR_PROP_BIT_INDICATE GATT_CHAR_PROP_BIT_INDICATE /* 0x20 */
+#define BTA_GATT_CHAR_PROP_BIT_AUTH GATT_CHAR_PROP_BIT_AUTH /* 0x40 */
+#define BTA_GATT_CHAR_PROP_BIT_EXT_PROP GATT_CHAR_PROP_BIT_EXT_PROP /* 0x80 */
+typedef UINT8 tBTA_GATT_CHAR_PROP;
+
+#ifndef BTA_GATTC_CHAR_DESCR_MAX
+#define BTA_GATTC_CHAR_DESCR_MAX 7
+#endif
+
+/*********************** NV callback Data Definitions **********************
+*/
+typedef struct
+{
+ tBT_UUID app_uuid128;
+ tBT_UUID svc_uuid;
+ UINT16 svc_inst;
+ UINT16 s_handle;
+ UINT16 e_handle;
+ BOOLEAN is_primary; /* primary service or secondary */
+} tBTA_GATTS_HNDL_RANGE;
+
+#define BTA_GATTS_SRV_CHG_CMD_ADD_CLIENT GATTS_SRV_CHG_CMD_ADD_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_UPDATE_CLIENT GATTS_SRV_CHG_CMD_UPDATE_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_REMOVE_CLIENT GATTS_SRV_CHG_CMD_REMOVE_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_READ_NUM_CLENTS GATTS_SRV_CHG_CMD_READ_NUM_CLENTS
+#define BTA_GATTS_SRV_CHG_CMD_READ_CLENT GATTS_SRV_CHG_CMD_READ_CLENT
+typedef tGATTS_SRV_CHG_CMD tBTA_GATTS_SRV_CHG_CMD;
+
+typedef tGATTS_SRV_CHG tBTA_GATTS_SRV_CHG;
+typedef tGATTS_SRV_CHG_REQ tBTA_GATTS_SRV_CHG_REQ;
+typedef tGATTS_SRV_CHG_RSP tBTA_GATTS_SRV_CHG_RSP;
+
+enum
+{
+ BTA_GATT_TRANSPORT_LE,
+ BTA_GATT_TRANSPORT_BR_EDR,
+ BTA_GATT_TRANSPORT_LE_BR_EDR
+};
+typedef UINT8 tBTA_GATT_TRANSPORT;
+
+/* attribute value */
+typedef tGATT_VALUE tBTA_GATT_VALUE;
+
+/* attribute response data */
+typedef tGATTS_RSP tBTA_GATTS_RSP;
+
+/* attribute request data from the client */
+#define BTA_GATT_PREP_WRITE_CANCEL 0x00
+#define BTA_GATT_PREP_WRITE_EXEC 0x01
+typedef tGATT_EXEC_FLAG tBTA_GATT_EXEC_FLAG;
+
+/* read request always based on UUID */
+typedef tGATT_READ_REQ tTA_GBATT_READ_REQ;
+
+/* write request data */
+typedef tGATT_WRITE_REQ tBTA_GATT_WRITE_REQ;
+
+/* callback data for server access request from client */
+typedef tGATTS_DATA tBTA_GATTS_REQ_DATA;
+
+typedef struct
+{
+ BD_ADDR remote_bda;
+ UINT32 trans_id;
+ UINT16 conn_id;
+ tBTA_GATTS_REQ_DATA *p_data;
+}tBTA_GATTS_REQ;
+
+typedef struct
+{
+ tBTA_GATTS_IF server_if;
+ tBTA_GATT_STATUS status;
+// btla-specific ++
+ tBT_UUID uuid;
+// btla-specific --
+}tBTA_GATTS_REG_OPER;
+
+
+typedef struct
+{
+ tBTA_GATTS_IF server_if;
+ UINT16 service_id;
+// btla-specific ++
+ UINT16 svc_instance;
+ BOOLEAN is_primary;
+ tBTA_GATT_STATUS status;
+ tBT_UUID uuid;
+// btla-specific --
+}tBTA_GATTS_CREATE;
+
+typedef struct
+{
+ tBTA_GATTS_IF server_if;
+ UINT16 service_id;
+ UINT16 attr_id;
+ tBTA_GATT_STATUS status;
+// btla-specific ++
+ tBT_UUID char_uuid;
+// btla-specific --
+}tBTA_GATTS_ADD_RESULT;
+
+typedef struct
+{
+ tBTA_GATTS_IF server_if;
+ UINT16 service_id;
+ tBTA_GATT_STATUS status;
+}tBTA_GATTS_SRVC_OPER;
+
+
+typedef struct
+{
+ tBTA_GATTS_IF server_if;
+ BD_ADDR remote_bda;
+ UINT16 conn_id;
+ tBTA_GATT_REASON reason; /* report disconnect reason */
+}tBTA_GATTS_CONN;
+
+/* GATTS callback data */
+typedef union
+{
+ tBTA_GATTS_REG_OPER reg_oper;
+ tBTA_GATTS_CREATE create;
+ tBTA_GATTS_SRVC_OPER srvc_oper;
+ tBTA_GATT_STATUS status; /* BTA_GATTS_CONF_EVT */
+ tBTA_GATTS_ADD_RESULT add_result; /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
+ add char : BTA_GATTS_ADD_CHAR_EVT
+ add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
+ tBTA_GATTS_REQ req_data;
+ tBTA_GATTS_CONN conn; /* BTA_GATTS_CONN_EVT */
+
+}tBTA_GATTS;
+
+
+/* Server callback function */
+typedef void (tBTA_GATTS_CBACK)(tBTA_GATTS_EVT event, tBTA_GATTS *p_data);
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************
+** Client Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_AppRegister
+**
+** Description This function is called to register application callbacks
+** with BTA GATTC module.
+**
+** Parameters p_app_uuid - applicaiton UUID
+** p_client_cb - pointer to the application callback function.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_AppDeregister
+**
+** Description This function is called to deregister an application
+** from BTA GATTC module.
+**
+** Parameters client_if - client interface identifier.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_AppDeregister (tBTA_GATTC_IF client_if);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_Open
+**
+** Description Open a direct connection or add a background auto connection
+** bd address
+**
+** Parameters client_if: server interface.
+** remote_bda: remote device BD address.
+** is_direct: direct connection or background auto connection
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_CancelOpen
+**
+** Description Open a direct connection or add a background auto connection
+** bd address
+**
+** Parameters client_if: server interface.
+** remote_bda: remote device BD address.
+** is_direct: direct connection or background auto connection
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_Close
+**
+** Description Close a connection to a GATT server.
+**
+** Parameters conn_id: connectino ID to be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Close(UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_ServiceSearchRequest
+**
+** Description This function is called to request a GATT service discovery
+** on a GATT server. This function report service search result
+** by a callback event, and followed by a service search complete
+** event.
+**
+** Parameters conn_id: connection ID.
+** p_srvc_uuid: a UUID of the service application is interested in.
+** If Null, discover for all services.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ServiceSearchRequest(UINT16 conn_id, tBT_UUID *p_srvc_uuid);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetFirstChar
+**
+** Description This function is called to find the first charatceristic of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_srvc_id: the service ID of which the characteristic is belonged to.
+** p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+** characteristic.
+** p_char_result: output parameter which will store the GATT
+** characteristic ID.
+** p_property: output parameter to carry the characteristic property.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_GetFirstChar (UINT16 conn_id,
+ tBTA_GATT_SRVC_ID *p_srvc_id,
+ tBT_UUID *p_char_uuid_cond,
+ tBTA_GATTC_CHAR_ID *p_char_result,
+ tBTA_GATT_CHAR_PROP *p_property);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetNextChar
+**
+** Description This function is called to find the next charatceristic of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_start_char_id: start the characteristic search from the next record
+** after the one identified by char_id.
+** p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+** characteristic.
+** p_char_result: output parameter which will store the GATT
+** characteristic ID.
+** p_property: output parameter, characteristic property.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_GetNextChar (UINT16 conn_id,
+ tBTA_GATTC_CHAR_ID *p_start_char_id,
+ tBT_UUID *p_char_uuid_cond,
+ tBTA_GATTC_CHAR_ID *p_char_result,
+ tBTA_GATT_CHAR_PROP *p_property);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetFirstCharDescr
+**
+** Description This function is called to find the first charatceristic descriptor of the
+** charatceristic on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_char_id: the characteristic ID of which the descriptor is belonged to.
+** p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
+** characteristic.
+** p_descr_result: output parameter which will store the GATT
+** characteristic descriptor ID.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+ tBT_UUID *p_descr_uuid_cond,
+ tBTA_GATTC_CHAR_DESCR_ID *p_descr_result);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetNextCharDescr
+**
+** Description This function is called to find the next charatceristic of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_start_descr_id: start the characteristic search from the next record
+** after the one identified by p_start_descr_id.
+** p_descr_uuid_cond: Characteristic descriptor UUID, if NULL find
+** the first available characteristic descriptor.
+** p_descr_result: output parameter which will store the GATT
+** characteristic descriptor ID.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_GetNextCharDescr (UINT16 conn_id,
+ tBTA_GATTC_CHAR_DESCR_ID *p_start_descr_id,
+ tBT_UUID *p_descr_uuid_cond,
+ tBTA_GATTC_CHAR_DESCR_ID *p_descr_result);
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetFirstIncludedService
+**
+** Description This function is called to find the first included service of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_srvc_id: the service ID of which the included service is belonged to.
+** p_uuid_cond: include service UUID, if NULL find the first available
+** included service.
+** p_result: output parameter which will store the GATT ID
+** of the included service found.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_GetFirstIncludedService(UINT16 conn_id,
+ tBTA_GATT_SRVC_ID *p_srvc_id,
+ tBT_UUID *p_uuid_cond,
+ tBTA_GATTC_INCL_SVC_ID *p_result);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_GetNextIncludedService
+**
+** Description This function is called to find the next included service of the
+** service on the given server.
+**
+** Parameters conn_id: connection ID which identify the server.
+** p_start_id: start the search from the next record
+** after the one identified by p_start_id.
+** p_uuid_cond: Included service UUID, if NULL find the first available
+** included service.
+** p_result: output parameter which will store the GATT ID
+** of the included service found.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
+ tBTA_GATTC_INCL_SVC_ID *p_start_id,
+ tBT_UUID *p_uuid_cond,
+ tBTA_GATTC_INCL_SVC_ID *p_result);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_ReadCharacteristic
+**
+** Description This function is called to read a service's characteristics of
+** the given characteritisc ID.
+**
+** Parameters conn_id - connectino ID.
+** p_char_id - characteritic ID to read.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ReadCharacteristic (UINT16 conn_id,
+ tBTA_GATTC_CHAR_ID *p_char_id,
+ tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_ReadCharDescr
+**
+** Description This function is called to read a characteristics descriptor.
+**
+** Parameters conn_id - connection ID.
+** p_char_descr_id - characteritic descriptor ID to read.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
+ tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+ tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_WriteCharValue
+**
+** Description This function is called to write characteristic value.
+**
+** Parameters conn_id - connection ID.
+** p_char_id - characteristic ID to write.
+** write_type - type of write.
+** len: length of the data to be written.
+** p_value - the value to be written.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_WriteCharValue (UINT16 conn_id,
+ tBTA_GATTC_CHAR_ID *p_char_id,
+ tBTA_GATTC_WRITE_TYPE write_type,
+ UINT16 len,
+ UINT8 *p_value,
+ tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_WriteCharDescr
+**
+** Description This function is called to write characteristic descriptor value.
+**
+** Parameters conn_id - connection ID
+** p_char_descr_id - characteristic descriptor ID to write.
+** write_type - type of write.
+** p_value - the value to be written.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
+ tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+ tBTA_GATTC_WRITE_TYPE write_type,
+ tBTA_GATT_UNFMT *p_data,
+ tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_SendIndConfirm
+**
+** Description This function is called to send handle value confirmation.
+**
+** Parameters conn_id - connection ID.
+** p_char_id - characteristic ID to confrim.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_RegisterForNotifications
+**
+** Description This function is called to register for notification of a service.
+**
+** Parameters client_if - client interface.
+** remote_bda - target GATT server.
+** p_char_id - pointer to GATT characteristic ID.
+**
+** Returns OK if registration succeed, otherwise failed.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
+ BD_ADDR remote_bda,
+ tBTA_GATTC_CHAR_ID *p_char_id);
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_DeregisterForNotifications
+**
+** Description This function is called to de-register for notification of a servbice.
+**
+** Parameters client_if - client interface.
+** remote_bda - target GATT server.
+** p_char_id - pointer to a GATT characteristic ID.
+**
+** Returns OK if deregistration succeed, otherwise failed.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
+ BD_ADDR remote_bda,
+ tBTA_GATTC_CHAR_ID *p_char_id);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_PrepareWrite
+**
+** Description This function is called to prepare write a characteristic value.
+**
+** Parameters conn_id - connection ID.
+** p_char_id - GATT characteritic ID of the service.
+** offset - offset of the write value.
+** len: length of the data to be written.
+** p_value - the value to be written.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_PrepareWrite (UINT16 conn_id,
+ tBTA_GATTC_CHAR_ID *p_char_id,
+ UINT16 offset,
+ UINT16 len,
+ UINT8 *p_value,
+ tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_ExecuteWrite
+**
+** Description This function is called to execute write a prepare write sequence.
+**
+** Parameters conn_id - connection ID.
+** is_execute - execute or cancel.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ExecuteWrite (UINT16 conn_id, BOOLEAN is_execute);
+
+/*******************************************************************************
+**
+** Function BTA_GATTC_ReadMultiple
+**
+** Description This function is called to read multiple characteristic or
+** characteristic descriptors.
+**
+** Parameters conn_id - connectino ID.
+** p_read_multi - read multiple parameters.
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
+ tBTA_GATT_AUTH_REQ auth_req);
+
+
+
+
+/*******************************************************************************
+** BTA GATT Server API
+********************************************************************************/
+/*******************************************************************************
+**
+** Function BTA_GATTS_AppRegister
+**
+** Description This function is called to register application callbacks
+** with BTA GATTS module.
+**
+** Parameters p_app_uuid - applicaiton UUID
+** p_cback - pointer to the application callback function.
+**
+** Returns None
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTS_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_AppDeregister
+**
+** Description De-register with BTA GATT Server.
+**
+** Parameters server_if: server interface
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_CreateService
+**
+** Description Create a service. When service creation is done, a callback
+** event BTA_GATTS_CREATE_SRVC_EVT is called to report status
+** and service ID to the profile. The service ID obtained in
+** the callback function needs to be used when adding included
+** service and characteristics/descriptors into the service.
+**
+** Parameters server_if: server interface.
+** p_service_uuid: service UUID.
+** inst: instance ID number of this service.
+** num_handle: numble of handle requessted for this service.
+** is_primary: is this service a primary one or not.
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, tBT_UUID *p_service_uuid,
+ UINT8 inst, UINT16 num_handle, BOOLEAN is_primary);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_AddIncludeService
+**
+** Description This function is called to add an included service. After included
+** service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
+** is reported the included service ID.
+**
+** Parameters service_id: service ID to which this included service is to
+** be added.
+** included_service_id: the service ID to be included.
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_AddCharacteristic
+**
+** Description This function is called to add a characteristic into a service.
+**
+** Parameters service_id: service ID to which this included service is to
+** be added.
+** p_char_uuid : Characteristic UUID.
+** perm : Characteristic value declaration attribute permission.
+** property : Characteristic Properties
+**
+** Returns None
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_AddCharacteristic (UINT16 service_id, tBT_UUID *p_char_uuid,
+ tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_AddCharDescriptor
+**
+** Description This function is called to add characteristic descriptor. When
+** it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
+** to report the status and an ID number for this descriptor.
+**
+** Parameters service_id: service ID to which this charatceristic descriptor is to
+** be added.
+** perm: descriptor access permission.
+** p_descr_uuid: descriptor UUID.
+** p_descr_params: descriptor value if it's read only descriptor.
+**
+** Returns returns status.
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
+ tBTA_GATT_PERM perm,
+ tBT_UUID * p_descr_uuid);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_DeleteService
+**
+** Description This function is called to delete a service. When this is done,
+** a callback event BTA_GATTS_DELETE_EVT is report with the status.
+**
+** Parameters service_id: service_id to be deleted.
+**
+** Returns returns none.
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_DeleteService(UINT16 service_id);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_StartService
+**
+** Description This function is called to start a service.
+**
+** Parameters service_id: the service ID to be started.
+** sup_transport: supported trasnport.
+**
+** Returns None.
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_StartService(UINT16 service_id, tBTA_GATT_TRANSPORT sup_transport);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_StopService
+**
+** Description This function is called to stop a service.
+**
+** Parameters service_id - service to be topped.
+**
+** Returns None
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_StopService(UINT16 service_id);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_HandleValueIndication
+**
+** Description This function is called to read a characteristics descriptor.
+**
+** Parameters conn_id - connection identifier.
+** attr_id - attribute ID to indicate.
+** data_len - indicate data length.
+** p_data: data to indicate.
+** need_confirm - if this indication expects a confirmation or not.
+**
+** Returns None
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id,
+ UINT16 data_len,
+ UINT8 *p_data,
+ BOOLEAN need_confirm);
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_SendRsp
+**
+** Description This function is called to send a response to a request.
+**
+** Parameters conn_id - connection identifier.
+** trans_id - transaction ID.
+** status - response status
+** p_msg - response data.
+**
+** Returns None
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
+ tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg);
+
+
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_Open
+**
+** Description Open a direct open connection or add a background auto connection
+** bd address
+**
+** Parameters server_if: server interface.
+** remote_bda: remote device BD address.
+** is_direct: direct connection or background auto connection
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_CancelOpen
+**
+** Description Cancel a direct open connection or remove a background auto connection
+** bd address
+**
+** Parameters server_if: server interface.
+** remote_bda: remote device BD address.
+** is_direct: direct connection or background auto connection
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+
+/*******************************************************************************
+**
+** Function BTA_GATTS_Close
+**
+** Description Close a connection a remote device.
+**
+** Parameters conn_id: connectino ID to be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_GATTS_Close(UINT16 conn_id);
+
+
+#ifdef __cplusplus
+
+}
+#endif
+
+
+#endif /* BTA_GATT_API_H */
+
diff --git a/bta/include/bta_gattc_ci.h b/bta/include/bta_gattc_ci.h
new file mode 100644
index 0000000..1525e3e
--- /dev/null
+++ b/bta/include/bta_gattc_ci.h
@@ -0,0 +1,120 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for GATT call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_CI_H
+#define BTA_GATTC_CI_H
+
+#include "bta_gatt_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* Open Complete Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATT_STATUS status;
+} tBTA_GATTC_CI_EVT;
+
+#define BTA_GATTC_NV_LOAD_MAX 10
+
+/* Read Ready Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_GATT_STATUS status;
+ UINT16 num_attr;
+ tBTA_GATTC_NV_ATTR attr[BTA_GATTC_NV_LOAD_MAX];
+} tBTA_GATTC_CI_LOAD;
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_gattc_ci_cache_open
+**
+** Description This function sends an event to indicate server cache open
+** completed.
+**
+** Parameters server_bda - server BDA of this cache.
+** status - BTA_GATT_OK if full buffer of data,
+** BTA_GATT_FAIL if an error has occurred.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_ci_cache_open(BD_ADDR server_bda, UINT16 evt,
+ tBTA_GATT_STATUS status, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function bta_gattc_ci_cache_load
+**
+** Description This function sends an event to BTA indicating the phone has
+** load the servere cache and ready to send it to the stack.
+**
+** Parameters server_bda - server BDA of this cache.
+** num_bytes_read - number of bytes read into the buffer
+** specified in the read callout-function.
+** status - BTA_GATT_OK if full buffer of data,
+** BTA_GATT_FAIL if an error has occurred.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_ci_cache_load(BD_ADDR server_bda, UINT16 evt,
+ UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_atrr,
+ tBTA_GATT_STATUS status, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function bta_gattc_ci_save
+**
+** Description This function sends an event to BTA indicating the phone has
+** save the server cache.
+**
+** Parameters server_bda - server BDA of this cache.
+** status - BTA_GATT_OK if full buffer of data,
+** BTA_GATT_FAIL if an error has occurred.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_ci_cache_save(BD_ADDR server_bda, UINT16 evt,
+ tBTA_GATT_STATUS status, UINT16 conn_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_GATTC_CI_H */
+
diff --git a/bta/include/bta_gattc_co.h b/bta/include/bta_gattc_co.h
new file mode 100644
index 0000000..d2392b8
--- /dev/null
+++ b/bta/include/bta_gattc_co.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for BTA GATT client call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_CO_H
+#define BTA_GATTC_CO_H
+
+#include "bta_gatt_api.h"
+
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_open
+**
+** Description This callout function is executed by GATTC when a GATT server
+** cache is ready to be sent.
+**
+** Parameter server_bda: server bd address of this cache belongs to
+** evt: call in event to be passed in when cache open is done.
+** conn_id: connection ID of this cache operation attach to.
+** to_save: open cache to save or to load.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt,
+ UINT16 conn_id, BOOLEAN to_save);
+
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_close
+**
+** Description This callout function is executed by GATTC when a GATT server
+** cache is written completely.
+**
+** Parameter server_bda: server bd address of this cache belongs to
+** conn_id: connection ID of this cache operation attach to.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_save
+**
+** Description This callout function is executed by GATT when a server cache
+** is available to save.
+**
+** Parameter server_bda: server bd address of this cache belongs to
+** evt: call in event to be passed in when cache save is done.
+** num_attr: number of attribute to be save.
+** p_attr: pointer to the list of attributes to save.
+** attr_index: starting attribute index of the save operation.
+** conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_save(BD_ADDR server_bda, UINT16 evt,
+ UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr,
+ UINT16 attr_index, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function bta_gattc_co_cache_load
+**
+** Description This callout function is executed by GATT when server cache
+** is required to load.
+**
+** Parameter server_bda: server bd address of this cache belongs to
+** evt: call in event to be passed in when cache save is done.
+** num_attr: number of attribute to be save.
+** attr_index: starting attribute index of the save operation.
+** conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt,
+ UINT16 start_index, UINT16 conn_id);
+
+#endif /* BTA_GATT_CO_H */
+
diff --git a/bta/include/bta_gatts_co.h b/bta/include/bta_gatts_co.h
new file mode 100644
index 0000000..86f65dc
--- /dev/null
+++ b/bta/include/bta_gatts_co.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for BTA GATT server call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTS_CO_H
+#define BTA_GATTS_CO_H
+
+#include "bta_gatt_api.h"
+
+/*******************************************************************************
+**
+** Function bta_gatts_co_update_handle_range
+**
+** Description This callout function is executed by GATTS when a GATT server
+** handle range ios to be added or removed.
+**
+** Parameter is_add: true is to add a handle range; otherwise is to delete.
+** p_hndl_range: handle range.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_gatts_co_update_handle_range(BOOLEAN is_add, tBTA_GATTS_HNDL_RANGE *p_hndl_range);
+
+/*******************************************************************************
+**
+** Function bta_gatts_co_srv_chg
+**
+** Description This call-out is to read/write/remove service change related
+** informaiton. The request consists of the cmd and p_req and the
+** response is returned in p_rsp
+**
+** Parameter cmd - request command
+** p_req - request paramters
+** p_rsp - response data for the request
+**
+** Returns TRUE - if the request is processed successfully and
+** the response is returned in p_rsp.
+** FASLE - if the request can not be processed
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_gatts_co_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
+ tBTA_GATTS_SRV_CHG_REQ *p_req,
+ tBTA_GATTS_SRV_CHG_RSP *p_rsp);
+
+/*******************************************************************************
+**
+** Function bta_gatts_co_load_handle_range
+**
+** Description This callout function is executed by GATTS when a GATT server
+** handle range is requested to be loaded from NV.
+**
+** Parameter
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
+ tBTA_GATTS_HNDL_RANGE *p_handle);
+
+
+#endif /* BTA_GATTS_CO_H */
+
diff --git a/bta/include/bta_hh_api.h b/bta/include/bta_hh_api.h
new file mode 100644
index 0000000..f613d30
--- /dev/null
+++ b/bta/include/bta_hh_api.h
@@ -0,0 +1,479 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2002-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#ifndef BTA_HH_API_H
+#define BTA_HH_API_H
+
+#include "bta_api.h"
+#include "hidh_api.h"
+
+/*****************************************************************************
+** Constants and Type Definitions
+*****************************************************************************/
+#ifndef BTA_HH_DEBUG
+#define BTA_HH_DEBUG FALSE
+#endif
+
+#ifndef BTA_HH_SSR_MAX_LATENCY_DEF
+#define BTA_HH_SSR_MAX_LATENCY_DEF 1600
+#endif
+
+#ifndef BTA_HH_SSR_MIN_TOUT_DEF
+#define BTA_HH_SSR_MIN_TOUT_DEF 2
+#endif
+
+/* BTA HID Host callback events */
+#define BTA_HH_ENABLE_EVT 0 /* HH enabled */
+#define BTA_HH_DISABLE_EVT 1 /* HH disabled */
+#define BTA_HH_OPEN_EVT 2 /* connection opened */
+#define BTA_HH_CLOSE_EVT 3 /* connection closed */
+#define BTA_HH_GET_RPT_EVT 4 /* BTA_HhGetReport callback */
+#define BTA_HH_SET_RPT_EVT 5 /* BTA_HhSetReport callback */
+#define BTA_HH_GET_PROTO_EVT 6 /* BTA_GetProtoMode callback */
+#define BTA_HH_SET_PROTO_EVT 7 /* BTA_HhSetProtoMode callback */
+#define BTA_HH_GET_IDLE_EVT 8 /* BTA_HhGetIdle comes callback */
+#define BTA_HH_SET_IDLE_EVT 9 /* BTA_HhSetIdle finish callback */
+#define BTA_HH_GET_DSCP_EVT 10 /* Get report descripotor */
+#define BTA_HH_ADD_DEV_EVT 11 /* Add Device callback */
+#define BTA_HH_RMV_DEV_EVT 12 /* remove device finished */
+#define BTA_HH_VC_UNPLUG_EVT 13 /* virtually unplugged */
+#define BTA_HH_UPDATE_UCD_EVT 14
+#define BTA_HH_API_ERR_EVT 15 /* API error is caught */
+
+typedef UINT16 tBTA_HH_EVT;
+
+/* defined the minimum offset */
+#define BTA_HH_MIN_OFFSET L2CAP_MIN_OFFSET+1
+
+#define BTA_HH_MAX_KNOWN HID_HOST_MAX_DEVICES
+/* invalid device handle */
+#define BTA_HH_INVALID_HANDLE 0xff
+
+/* type of protocol mode */
+#define BTA_HH_PROTO_RPT_MODE (0x00)
+#define BTA_HH_PROTO_BOOT_MODE (0x01)
+#define BTA_HH_PROTO_UNKNOWN (0xff)
+typedef UINT8 tBTA_HH_PROTO_MODE;
+
+enum
+{
+ BTA_HH_KEYBD_RPT_ID = 1,
+ BTA_HH_MOUSE_RPT_ID
+};
+typedef UINT8 tBTA_HH_BOOT_RPT_ID;
+
+/* type of devices, bit mask */
+#define BTA_HH_DEVT_UNKNOWN 0x00
+#define BTA_HH_DEVT_JOS 0x01 /* joy stick */
+#define BTA_HH_DEVT_GPD 0x02 /* game pad */
+#define BTA_HH_DEVT_RMC 0x03 /* remote control */
+#define BTA_HH_DEVT_SED 0x04 /* sensing device */
+#define BTA_HH_DEVT_DGT 0x05 /* Digitizer tablet */
+#define BTA_HH_DEVT_CDR 0x06 /* card reader */
+#define BTA_HH_DEVT_KBD 0x10 /* keyboard */
+#define BTA_HH_DEVT_MIC 0x20 /* pointing device */
+#define BTA_HH_DEVT_COM 0x30 /* Combo keyboard/pointing */
+#define BTA_HH_DEVT_OTHER 0x80
+typedef UINT8 tBTA_HH_DEVT;
+
+enum
+{
+ BTA_HH_OK,
+ BTA_HH_HS_HID_NOT_READY, /* handshake error : device not ready */
+ BTA_HH_HS_INVALID_RPT_ID, /* handshake error : invalid report ID */
+ BTA_HH_HS_TRANS_NOT_SPT, /* handshake error : transaction not spt */
+ BTA_HH_HS_INVALID_PARAM, /* handshake error : invalid paremter */
+ BTA_HH_HS_ERROR, /* handshake error : unspecified HS error */
+ BTA_HH_ERR, /* general BTA HH error */
+ BTA_HH_ERR_SDP, /* SDP error */
+ BTA_HH_ERR_PROTO, /* SET_Protocol error,
+ only used in BTA_HH_OPEN_EVT callback */
+ BTA_HH_ERR_DB_FULL, /* device database full error, used in
+ BTA_HH_OPEN_EVT/BTA_HH_ADD_DEV_EVT */
+ BTA_HH_ERR_TOD_UNSPT, /* type of device not supported */
+ BTA_HH_ERR_NO_RES, /* out of system resources */
+ BTA_HH_ERR_AUTH_FAILED, /* authentication fail */
+ BTA_HH_ERR_HDL
+};
+typedef UINT8 tBTA_HH_STATUS;
+
+
+#define BTA_HH_VIRTUAL_CABLE HID_VIRTUAL_CABLE
+#define BTA_HH_NORMALLY_CONNECTABLE HID_NORMALLY_CONNECTABLE
+#define BTA_HH_RECONN_INIT HID_RECONN_INIT
+#define BTA_HH_SDP_DISABLE HID_SDP_DISABLE
+#define BTA_HH_BATTERY_POWER HID_BATTERY_POWER
+#define BTA_HH_REMOTE_WAKE HID_REMOTE_WAKE
+#define BTA_HH_SUP_TOUT_AVLBL HID_SUP_TOUT_AVLBL
+#define BTA_HH_SEC_REQUIRED HID_SEC_REQUIRED
+typedef UINT16 tBTA_HH_ATTR_MASK;
+
+
+/* supported type of device and corresponding application ID */
+typedef struct
+{
+ tBTA_HH_DEVT tod; /* type of device */
+ UINT8 app_id; /* corresponding application ID */
+}tBTA_HH_SPT_TOD;
+
+/* configuration struct */
+typedef struct
+{
+ UINT8 max_devt_spt; /* max number of types of devices spt */
+ tBTA_HH_SPT_TOD *p_devt_list; /* supported types of device list */
+ UINT16 sdp_db_size;
+}tBTA_HH_CFG;
+
+enum
+{
+ BTA_HH_RPTT_RESRV, /* reserved */
+ BTA_HH_RPTT_INPUT, /* input report */
+ BTA_HH_RPTT_OUTPUT, /* output report */
+ BTA_HH_RPTT_FEATURE /* feature report */
+};
+typedef UINT8 tBTA_HH_RPT_TYPE;
+
+/* HID_CONTROL operation code used in BTA_HhSendCtrl()
+*/
+enum
+{
+ BTA_HH_CTRL_NOP = 0 + HID_PAR_CONTROL_NOP ,/* mapping from BTE */
+ BTA_HH_CTRL_HARD_RESET, /* hard reset */
+ BTA_HH_CTRL_SOFT_RESET, /* soft reset */
+ BTA_HH_CTRL_SUSPEND, /* enter suspend */
+ BTA_HH_CTRL_EXIT_SUSPEND, /* exit suspend */
+ BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG /* virtual unplug */
+};
+typedef UINT8 tBTA_HH_TRANS_CTRL_TYPE;
+
+typedef tHID_DEV_DSCP_INFO tBTA_HH_DEV_DESCR;
+
+/* id DI is not existing in remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be set to 0xffff */
+#define BTA_HH_VENDOR_ID_INVALID 0xffff
+
+
+/* report descriptor information */
+typedef struct
+{
+ UINT16 vendor_id; /* vendor ID */
+ UINT16 product_id; /* product ID */
+ UINT16 version; /* version */
+ UINT16 ssr_max_latency; /* SSR max latency */
+ UINT16 ssr_min_tout; /* SSR min timeout */
+ UINT8 ctry_code; /*Country Code.*/
+ tBTA_HH_DEV_DESCR descriptor;
+}tBTA_HH_DEV_DSCP_INFO;
+
+/* callback event data for BTA_HH_OPEN_EVT */
+typedef struct
+{
+ BD_ADDR bda; /* HID device bd address */
+ tBTA_HH_STATUS status; /* operation status */
+ UINT8 handle; /* device handle */
+} tBTA_HH_CONN;
+
+typedef tBTA_HH_CONN tBTA_HH_DEV_INFO;
+
+/* callback event data */
+typedef struct
+{
+ tBTA_HH_STATUS status; /* operation status */
+ UINT8 handle; /* device handle */
+} tBTA_HH_CBDATA;
+
+enum
+{
+ BTA_HH_MOD_CTRL_KEY,
+ BTA_HH_MOD_SHFT_KEY,
+ BTA_HH_MOD_ALT_KEY,
+ BTA_HH_MOD_GUI_KEY,
+ BTA_HH_MOD_MAX_KEY
+};
+
+/* parsed boot mode keyboard report */
+typedef struct
+{
+ UINT8 this_char[6]; /* virtual key code */
+ BOOLEAN mod_key[BTA_HH_MOD_MAX_KEY];
+ /* ctrl, shift, Alt, GUI */
+ /* modifier key: is Shift key pressed */
+ /* modifier key: is Ctrl key pressed */
+ /* modifier key: is Alt key pressed */
+ /* modifier key: GUI up/down */
+ BOOLEAN caps_lock; /* is caps locked */
+ BOOLEAN num_lock; /* is Num key pressed */
+} tBTA_HH_KEYBD_RPT;
+
+/* parsed boot mode mouse report */
+typedef struct
+{
+ UINT8 mouse_button; /* mouse button is clicked */
+ INT8 delta_x; /* displacement x */
+ INT8 delta_y; /* displacement y */
+}tBTA_HH_MICE_RPT;
+
+/* parsed Boot report */
+typedef struct
+{
+ tBTA_HH_BOOT_RPT_ID dev_type; /* type of device report */
+ union
+ {
+ tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */
+ tBTA_HH_MICE_RPT mice_rpt; /* mouse report */
+ } data_rpt;
+} tBTA_HH_BOOT_RPT;
+
+/* handshake data */
+typedef struct
+{
+ tBTA_HH_STATUS status; /* handshake status */
+ UINT8 handle; /* device handle */
+ union
+ {
+ tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */
+ BT_HDR *p_rpt_data; /* GET_RPT_EVT : report data */
+ UINT8 idle_rate; /* GET_IDLE_EVT : idle rate */
+ } rsp_data;
+
+}tBTA_HH_HSDATA;
+
+/* union of data associated with HD callback */
+typedef union
+{
+ tBTA_HH_DEV_INFO dev_info; /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT */
+ tBTA_HH_CONN conn; /* BTA_HH_OPEN_EVT */
+ tBTA_HH_CBDATA dev_status; /* BTA_HH_CLOSE_EVT,
+ BTA_HH_SET_PROTO_EVT
+ BTA_HH_SET_RPT_EVT
+ BTA_HH_SET_IDLE_EVT */
+
+ tBTA_HH_STATUS status; /* BTA_HH_ENABLE_EVT */
+ tBTA_HH_DEV_DSCP_INFO dscp_info; /* BTA_HH_GET_DSCP_EVT */
+ tBTA_HH_HSDATA hs_data; /* GET_ transaction callback
+ BTA_HH_GET_RPT_EVT
+ BTA_HH_GET_PROTO_EVT
+ BTA_HH_GET_IDLE_EVT */
+} tBTA_HH;
+
+/* BTA HH callback function */
+typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data);
+
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function BTA_HhRegister
+**
+** Description This function enable HID host and registers HID-Host with
+** lower layers.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_HhDeregister
+**
+** Description This function is called when the host is about power down.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_HhOpen
+**
+** Description This function is called to start an inquiry and read SDP
+** record of responding devices; connect to a device if only
+** one active HID device is found.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhOpen (BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode,
+ tBTA_SEC sec_mask);
+
+/*******************************************************************************
+**
+** Function BTA_HhClose
+**
+** Description This function disconnects the device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhClose(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function BTA_HhSetProtoMode
+**
+** Description This function set the protocol mode at specified HID handle
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSetProtoMode(UINT8 handle, tBTA_HH_PROTO_MODE t_type);
+
+/*******************************************************************************
+**
+** Function BTA_HhGetProtoMode
+**
+** Description This function get the protocol mode of a specified HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetProtoMode(UINT8 dev_handle);
+/*******************************************************************************
+**
+** Function BTA_HhSetReport
+**
+** Description send SET_REPORT to device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type,
+ BT_HDR *p_data);
+
+/*******************************************************************************
+**
+** Function BTA_HhGetReport
+**
+** Description Send a GET_REPORT to HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type,
+ UINT8 rpt_id, UINT16 buf_size);
+/*******************************************************************************
+**
+** Function BTA_HhSendCtrl
+**
+** Description Send HID_CONTROL request to a HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSendCtrl(UINT8 dev_handle,
+ tBTA_HH_TRANS_CTRL_TYPE c_type);
+
+/*******************************************************************************
+**
+** Function BTA_HhSetIdle
+**
+** Description send SET_IDLE to device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate);
+
+
+/*******************************************************************************
+**
+** Function BTA_HhGetIdle
+**
+** Description Send a GET_IDLE from HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetIdle(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function BTA_HhSendData
+**
+** Description Send DATA transaction to a HID device.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR *p_buf);
+
+/*******************************************************************************
+**
+** Function BTA_HhGetDscpInfo
+**
+** Description Get report descriptor of the device
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetDscpInfo(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function BTA_HhAddDev
+**
+** Description Add a virtually cabled device into HID-Host device list
+** to manage and assign a device handle for future API call,
+** host applciation call this API at start-up to initialize its
+** virtually cabled devices.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask,
+ UINT8 sub_class, UINT8 app_id,
+ tBTA_HH_DEV_DSCP_INFO dscp_info);
+/*******************************************************************************
+**
+** Function BTA_HhRemoveDev
+**
+** Description Remove a device from the HID host devices list.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhRemoveDev(UINT8 dev_handle );
+/*******************************************************************************
+**
+** Parsing Utility Functions
+**
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function BTA_HhParseBootRpt
+**
+** Description This utility function parse a boot mode report.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
+ UINT16 report_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_HH_API_H */
diff --git a/bta/include/bta_hh_co.h b/bta/include/bta_hh_co.h
new file mode 100644
index 0000000..8f648df
--- /dev/null
+++ b/bta/include/bta_hh_co.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2005-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for hid host call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_HH_CO_H
+#define BTA_HH_CO_H
+
+#include "bta_hh_api.h"
+
+
+/*******************************************************************************
+**
+** Function bta_hh_co_data
+**
+** Description This callout function is executed by HH when data is received
+** in interupt channel.
+**
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len,
+ tBTA_HH_PROTO_MODE mode, UINT8 sub_class,
+ UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_hh_co_open
+**
+** Description This callout function is executed by HH when connection is
+** opened, and application may do some device specific
+** initialization.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class,
+ UINT16 attr_mask, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_hh_co_close
+**
+** Description This callout function is executed by HH when connection is
+** closed, and device specific finalizatio nmay be needed.
+**
+** Returns void.
+**
+*******************************************************************************/
+BTA_API extern void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id);
+
+#endif /* BTA_HH_CO_H */
+
diff --git a/bta/include/bta_hl_api.h b/bta/include/bta_hl_api.h
new file mode 100644
index 0000000..e7febf8
--- /dev/null
+++ b/bta/include/bta_hl_api.h
@@ -0,0 +1,908 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the HeaLth device profile (HL)
+ * subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ * phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_HL_API_H
+#define BTA_HL_API_H
+
+#include "bta_api.h"
+#include "btm_api.h"
+#include "mca_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+/* Extra Debug Code */
+#ifndef BTA_HL_DEBUG
+#define BTA_HL_DEBUG TRUE
+#endif
+
+#ifndef BTA_HL_NUM_APPS
+#define BTA_HL_NUM_APPS 3
+#endif
+
+#ifndef BTA_HL_NUM_MDEPS
+#define BTA_HL_NUM_MDEPS 5
+#endif
+
+#ifndef BTA_HL_NUM_MCLS
+#define BTA_HL_NUM_MCLS 7
+#endif
+
+#ifndef BTA_HL_NUM_MDLS_PER_MDEP
+#define BTA_HL_NUM_MDLS_PER_MDEP 4
+#endif
+
+#ifndef BTA_HL_NUM_MDLS_PER_MCL
+#define BTA_HL_NUM_MDLS_PER_MCL 10
+#endif
+
+#ifndef BTA_HL_NUM_DATA_TYPES
+#define BTA_HL_NUM_DATA_TYPES 5 /* maximum number of data types can be supported
+ per MDEP ID */
+#endif
+
+#define BTA_HL_MCAP_RSP_TOUT 2 /* 2 seconds */
+
+#ifndef BTA_HL_CCH_NUM_FILTER_ELEMS
+#define BTA_HL_CCH_NUM_FILTER_ELEMS 3
+#endif
+
+#ifndef BTA_HL_NUM_SDP_CBACKS
+#define BTA_HL_NUM_SDP_CBACKS 7
+#endif
+
+#ifndef BTA_HL_NUM_SDP_RECS
+#define BTA_HL_NUM_SDP_RECS 3
+#endif
+
+#ifndef BTA_HL_NUM_SDP_MDEPS
+#define BTA_HL_NUM_SDP_MDEPS 10
+#endif
+
+#ifndef BTA_HL_NUM_SVC_ELEMS
+#define BTA_HL_NUM_SVC_ELEMS 2
+#endif
+
+#ifndef BTA_HL_NUM_PROTO_ELEMS
+#define BTA_HL_NUM_PROTO_ELEMS 2
+#endif
+
+#define BTA_HL_VERSION_01_00 0x0100
+#define BTA_HL_NUM_ADD_PROTO_LISTS 1
+#define BTA_HL_NUM_ADD_PROTO_ELEMS 2
+#define BTA_HL_MDEP_SEQ_SIZE 20
+#define BTA_HL_VAL_ARRY_SIZE 320
+
+#ifndef BTA_HL_NUM_MDL_CFGS
+#define BTA_HL_NUM_MDL_CFGS 16 /* numer of MDL cfg saved in the persistent memory*/
+#endif
+
+#define BTA_HL_NUM_TIMERS 7
+
+#define BTA_HL_CCH_RSP_TOUT 2000
+#define BTA_HL_LRG_POOL_ID GKI_POOL_ID_7
+#define BTA_HL_MAX_TIME 255
+#define BTA_HL_MIN_TIME 1
+#define BTA_HL_INVALID_APP_HANDLE 0xFF
+#define BTA_HL_INVALID_MCL_HANDLE 0xFF
+#define BTA_HL_INVALID_MDL_HANDLE 0xFFFF
+
+#define BTA_HL_STATUS_OK 0
+#define BTA_HL_STATUS_FAIL 1 /* Used to pass all other errors */
+#define BTA_HL_STATUS_ABORTED 2
+#define BTA_HL_STATUS_NO_RESOURCE 3
+#define BTA_HL_STATUS_LAST_ITEM 4
+#define BTA_HL_STATUS_DUPLICATE_APP_ID 5
+#define BTA_HL_STATUS_INVALID_APP_HANDLE 6
+#define BTA_HL_STATUS_INVALID_MCL_HANDLE 7
+#define BTA_HL_STATUS_MCAP_REG_FAIL 8
+#define BTA_HL_STATUS_MDEP_CO_FAIL 9
+#define BTA_HL_STATUS_ECHO_CO_FAIL 10
+#define BTA_HL_STATUS_MDL_CFG_CO_FAIL 11
+#define BTA_HL_STATUS_SDP_NO_RESOURCE 12
+#define BTA_HL_STATUS_SDP_FAIL 13
+#define BTA_HL_STATUS_NO_CCH 14
+#define BTA_HL_STATUS_NO_MCL 15
+
+#define BTA_HL_STATUS_NO_FIRST_RELIABLE 17
+#define BTA_HL_STATUS_INVALID_DCH_CFG 18
+#define BTA_HL_STATUS_INVALID_MDL_HANDLE 19
+#define BTA_HL_STATUS_INVALID_BD_ADDR 20
+#define BTA_HL_STATUS_INVALID_RECONNECT_CFG 21
+#define BTA_HL_STATUS_ECHO_TEST_BUSY 22
+#define BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID 23
+#define BTA_HL_STATUS_INVALID_MDL_ID 24
+#define BTA_HL_STATUS_NO_MDL_ID_FOUND 25
+#define BTA_HL_STATUS_DCH_BUSY 26 /* DCH is congested*/
+#define BTA_HL_STATUS_INVALID_CTRL_PSM 27
+
+typedef UINT8 tBTA_HL_STATUS;
+typedef tMCA_HANDLE tBTA_HL_APP_HANDLE;
+typedef tMCA_CL tBTA_HL_MCL_HANDLE;
+typedef tMCA_DL tBTA_HL_MDL_HANDLE;
+enum
+{
+ BTA_HL_DEVICE_TYPE_SINK,
+ BTA_HL_DEVICE_TYPE_SOURCE,
+ BTA_HL_DEVICE_TYPE_DUAL
+};
+
+typedef UINT8 tBTA_HL_DEVICE_TYPE;
+
+
+
+#define BTA_HL_SDP_IEEE_11073_20601 0x01
+
+#define BTA_HL_MCAP_SUP_RECONNECT_MASK_INIT 2 /* 0x02 */
+#define BTA_HL_MCAP_SUP_RECONNECT_MASK_ACCEPT 4 /* 0x04 */
+#define BTA_HL_MCAP_SUP_CSP_MASK_SYNC_SLAVE 0 /* 0x08 */
+#define BTA_HL_MCAP_SUP_CSP_MASK_SYNC_MASTER 0 /* 0x10 */
+
+#define BTA_HL_MCAP_SUP_PROC_MASK (BTA_HL_MCAP_SUP_RECONNECT_MASK_INIT | \
+ BTA_HL_MCAP_SUP_RECONNECT_MASK_ACCEPT | \
+ BTA_HL_MCAP_SUP_CSP_MASK_SYNC_SLAVE | \
+ BTA_HL_MCAP_SUP_CSP_MASK_SYNC_MASTER)
+#define BTA_HL_MDEP_ROLE_SOURCE 0x00
+#define BTA_HL_MDEP_ROLE_SINK 0x01
+
+typedef UINT8 tBTA_HL_MDEP_ROLE;
+
+#define BTA_HL_MDEP_ROLE_MASK_SOURCE 0x01 /* bit mask */
+#define BTA_HL_MDEP_ROLE_MASK_SINK 0x02
+typedef UINT8 tBTA_HL_MDEP_ROLE_MASK;
+
+
+#define BTA_HL_ECHO_TEST_MDEP_ID 0
+#define BTA_HL_ECHO_TEST_MDEP_CFG_IDX 0
+
+#define BTA_HL_INVALID_MDEP_ID 0xFF
+typedef tMCA_DEP tBTA_HL_MDEP_ID; /* 0 is for echo test,
+ 0x01-0x7F availave for use,
+ 0x80-0xFF reserved*/
+
+
+#define BTA_HL_DELETE_ALL_MDL_IDS 0xFFFF
+#define BTA_HL_MAX_MDL_VAL 0xFEFF
+typedef UINT16 tBTA_HL_MDL_ID; /* 0x0000 reserved,
+ 0x0001-0xFEFF dynamic range,
+ 0xFF00-0xFFFE reserved,
+ 0xFFFF indicates all MDLs*/
+
+#define BTA_HL_MDEP_DESP_LEN 35
+
+#define BTA_HL_DCH_MODE_RELIABLE 0
+#define BTA_HL_DCH_MODE_STREAMING 1
+
+typedef UINT8 tBTA_HL_DCH_MODE;
+
+#define BTA_HL_DCH_CFG_NO_PREF 0
+#define BTA_HL_DCH_CFG_RELIABLE 1
+#define BTA_HL_DCH_CFG_STREAMING 2
+#define BTA_HL_DCH_CFG_UNKNOWN 0xFF
+
+typedef UINT8 tBTA_HL_DCH_CFG;
+
+/* The Default DCH CFG for the echo test when the device is a Source */
+#define BTA_HL_DEFAULT_ECHO_TEST_SRC_DCH_CFG BTA_HL_DCH_CFG_RELIABLE
+
+#define BTA_HL_DCH_CREATE_RSP_SUCCESS 0
+#define BTA_HL_DCH_CREATE_RSP_CFG_REJ 1
+
+typedef UINT8 tBTA_HL_DCH_CREATE_RSP;
+
+#define BTA_HL_MCAP_SUP_PROC_RECONNECT_INIT 0x02
+#define BTA_HL_MCAP_SUP_PROC_RECONNECT_APT 0x04
+#define BTA_HL_MCAP_SUP_PROC_CSP_SLAVE 0x08
+#define BTA_HL_MCAP_SUP_PROC_CSP_MASTER 0x10
+
+typedef UINT8 tBTA_HL_SUP_PROC_MASK;
+
+typedef struct
+{
+ UINT16 max_rx_apdu_size; /* local rcv MTU */
+ UINT16 max_tx_apdu_size; /* maximum TX APDU size*/
+} tBTA_HL_ECHO_CFG;
+
+
+typedef struct
+{
+ UINT16 data_type;
+ UINT16 max_rx_apdu_size; /* local rcv MTU */
+ UINT16 max_tx_apdu_size; /* maximum TX APDU size*/
+ char desp[BTA_HL_MDEP_DESP_LEN+1];
+} tBTA_HL_MDEP_DATA_TYPE_CFG;
+
+
+typedef struct
+{
+ tBTA_HL_MDEP_ROLE mdep_role;
+ UINT8 num_of_mdep_data_types;
+ tBTA_HL_MDEP_DATA_TYPE_CFG data_cfg[BTA_HL_NUM_DATA_TYPES];
+} tBTA_HL_MDEP_CFG;
+
+typedef struct
+{
+ tBTA_HL_MDEP_ID mdep_id; /* MDEP ID 0x01-0x7F */
+ tBTA_HL_MDEP_CFG mdep_cfg;
+} tBTA_HL_MDEP;
+
+typedef struct
+{
+ tBTA_HL_MDEP mdep[BTA_HL_NUM_MDEPS];
+ tBTA_HL_ECHO_CFG echo_cfg;
+ tBTA_HL_MDEP_ROLE_MASK app_role_mask;
+ BOOLEAN advertize_source_sdp;
+ UINT8 num_of_mdeps;
+} tBTA_HL_SUP_FEATURE;
+
+typedef struct
+{
+ BOOLEAN delete_req_pending;
+ tBTA_HL_MDL_ID mdl_id;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+} tBTA_HL_DELETE_MDL;
+
+typedef struct
+{
+ UINT8 time;
+ UINT16 mtu;
+ tBTA_HL_MDL_ID mdl_id;
+ tBTA_HL_MDEP_ID local_mdep_id;
+ tBTA_HL_MDEP_ROLE local_mdep_role;
+ BOOLEAN active; /* true if this item is in use */
+ tBTA_HL_DCH_MODE dch_mode;
+ UINT8 fcs;
+ BD_ADDR peer_bd_addr;
+} tBTA_HL_MDL_CFG;
+
+
+/* Maximum number of supported feature list items (list_elem in tSDP_SUP_FEATURE_ELEM) */
+#define BTA_HL_NUM_SUP_FEATURE_ELEMS 10
+#define BTA_HL_SUP_FEATURE_SDP_BUF_SIZE 512
+/* This structure is used to add supported feature lists and find supported feature elements */
+typedef struct
+{
+ UINT8 mdep_id;
+ UINT16 data_type;
+ tBTA_HL_MDEP_ROLE mdep_role;
+ char *p_mdep_desp;
+} tBTA_HL_SUP_FEATURE_ELEM;
+
+typedef struct
+{
+ UINT16 num_elems;
+ tBTA_HL_SUP_FEATURE_ELEM list_elem[BTA_HL_NUM_SUP_FEATURE_ELEMS];
+} tBTA_HL_SUP_FEATURE_LIST_ELEM;
+
+
+typedef struct
+{
+ tBTA_HL_DEVICE_TYPE dev_type; /* sink, source or dual roles */
+ tBTA_SEC sec_mask; /* security mask for accepting conenction*/
+ const char *p_srv_name; /* service name to be used in the SDP; null terminated*/
+ const char *p_srv_desp; /* service description to be used in the SDP; null terminated */
+ const char *p_provider_name; /* provide name to be used in the SDP; null terminated */
+} tBTA_HL_REG_PARAM;
+
+typedef struct
+{
+ UINT16 ctrl_psm;
+ BD_ADDR bd_addr; /* Address of peer device */
+ tBTA_SEC sec_mask; /* security mask for initiating connection*/
+} tBTA_HL_CCH_OPEN_PARAM;
+
+
+typedef struct
+{
+ UINT16 ctrl_psm;
+ tBTA_HL_MDEP_ID local_mdep_id; /* local MDEP ID */
+ tBTA_HL_MDEP_ID peer_mdep_id; /* peer mdep id */
+ tBTA_HL_DCH_CFG local_cfg;
+ tBTA_SEC sec_mask; /* security mask for initiating connection*/
+} tBTA_HL_DCH_OPEN_PARAM;
+
+
+typedef struct
+{
+ UINT16 ctrl_psm;
+ tBTA_HL_MDL_ID mdl_id;
+} tBTA_HL_DCH_RECONNECT_PARAM;
+
+
+typedef struct
+{
+ UINT16 ctrl_psm;
+ UINT16 pkt_size;
+ tBTA_HL_DCH_CFG local_cfg;
+} tBTA_HL_DCH_ECHO_TEST_PARAM;
+
+typedef struct
+{
+ UINT16 buf_size;
+ UINT8 p_buf; /* buffer pointer */
+} tBTA_HL_DCH_BUF_INFO;
+
+typedef struct
+{
+ tBTA_HL_MDEP_ID local_mdep_id; /* local MDEP ID */
+ tBTA_HL_MDL_ID mdl_id;
+ tBTA_HL_DCH_CREATE_RSP rsp_code;
+ tBTA_HL_DCH_CFG cfg_rsp;
+} tBTA_HL_DCH_CREATE_RSP_PARAM;
+
+typedef struct
+{
+ UINT16 data_type;
+ UINT8 mdep_id;
+ tBTA_HL_MDEP_ROLE mdep_role;
+ char mdep_desp[BTA_HL_MDEP_DESP_LEN+1];
+}tBTA_HL_SDP_MDEP_CFG;
+
+typedef struct
+{
+ UINT16 ctrl_psm;
+ UINT16 data_psm;
+ UINT8 mcap_sup_proc;
+ UINT8 num_mdeps; /* number of mdep elements from SDP*/
+ char srv_name[BTA_SERVICE_NAME_LEN+1];
+ char srv_desp[BTA_SERVICE_DESP_LEN+1];
+ char provider_name[BTA_PROVIDER_NAME_LEN+1];
+ tBTA_HL_SDP_MDEP_CFG mdep_cfg[BTA_HL_NUM_SDP_MDEPS];
+} tBTA_HL_SDP_REC;
+
+typedef struct
+{
+ UINT8 num_recs;
+ tBTA_HL_SDP_REC sdp_rec[BTA_HL_NUM_SDP_RECS];
+} tBTA_HL_SDP;
+
+/* HL control callback function events */
+enum
+{
+ BTA_HL_CTRL_ENABLE_CFM_EVT = 0,
+ BTA_HL_CTRL_DISABLE_CFM_EVT
+};
+typedef UINT8 tBTA_HL_CTRL_EVT;
+/* Structure associated with BTA_HL_ENABLE_EVT
+ BTA_HL_DISABLE_EVT */
+
+typedef struct
+{
+ tBTA_HL_STATUS status;
+} tBTA_HL_CTRL_ENABLE_DISABLE;
+
+typedef union
+{
+ tBTA_HL_CTRL_ENABLE_DISABLE enable_cfm;
+ tBTA_HL_CTRL_ENABLE_DISABLE disable_cfm;
+} tBTA_HL_CTRL;
+
+/* HL instance callback function events */
+enum
+{
+ BTA_HL_REGISTER_CFM_EVT =0,
+ BTA_HL_DEREGISTER_CFM_EVT,
+ BTA_HL_CCH_OPEN_IND_EVT,
+ BTA_HL_CCH_OPEN_CFM_EVT,
+ BTA_HL_CCH_CLOSE_IND_EVT,
+ BTA_HL_CCH_CLOSE_CFM_EVT,
+ BTA_HL_DCH_CREATE_IND_EVT,
+ BTA_HL_DCH_OPEN_IND_EVT,
+ BTA_HL_DCH_OPEN_CFM_EVT,
+ BTA_HL_DCH_CLOSE_IND_EVT,
+ BTA_HL_DCH_CLOSE_CFM_EVT,
+ BTA_HL_DCH_RECONNECT_IND_EVT,
+ BTA_HL_DCH_RECONNECT_CFM_EVT,
+
+ BTA_HL_DCH_ABORT_IND_EVT,
+ BTA_HL_DCH_ABORT_CFM_EVT,
+ BTA_HL_DELETE_MDL_IND_EVT,
+ BTA_HL_DELETE_MDL_CFM_EVT,
+ BTA_HL_DCH_SEND_DATA_CFM_EVT,
+ BTA_HL_DCH_RCV_DATA_IND_EVT,
+ BTA_HL_CONG_CHG_IND_EVT,
+ BTA_HL_DCH_ECHO_TEST_CFM_EVT,
+ BTA_HL_SDP_QUERY_CFM_EVT,
+ BTA_HL_SDP_INFO_IND_EVT
+};
+typedef UINT8 tBTA_HL_EVT;
+
+
+typedef struct
+{
+ tBTA_HL_STATUS status; /* start status */
+ UINT8 app_id;
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_REGISTER_CFM;
+
+
+typedef struct
+{
+ tBTA_HL_STATUS status; /* start status */
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_DEREGISTER_CFM;
+
+
+typedef struct
+{
+ BOOLEAN intentional;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_CCH_CLOSE_IND;
+
+
+typedef struct
+{
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_MCL_IND;
+
+typedef struct
+{
+ tBTA_HL_STATUS status; /* connection status */
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_MCL_CFM;
+
+typedef struct
+{
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+ BD_ADDR bd_addr; /* address of peer device */
+} tBTA_HL_CCH_OPEN_IND;
+
+typedef struct
+{
+ tBTA_HL_STATUS status; /* connection status */
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+ BD_ADDR bd_addr; /* address of peer device */
+} tBTA_HL_CCH_OPEN_CFM;
+
+typedef struct
+{
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+ tBTA_HL_MDEP_ID local_mdep_id;
+ tBTA_HL_MDL_ID mdl_id; /* MCAP data link ID for this
+ data channel conenction */
+ tBTA_HL_DCH_CFG cfg; /* dch cfg requested by the peer device */
+} tBTA_HL_DCH_CREATE_IND;
+
+typedef struct
+{
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+ tBTA_HL_MDEP_ID local_mdep_id;
+ tBTA_HL_MDL_ID mdl_id; /* MCAP data link ID for this
+ data channel conenction */
+ tBTA_HL_DCH_MODE dch_mode; /* data channel mode - reliable or streaming*/
+
+ BOOLEAN first_reliable; /* whether this is the first reliable data channel */
+ UINT16 mtu;
+} tBTA_HL_DCH_OPEN_IND;
+
+typedef struct
+{
+ tBTA_HL_STATUS status; /* connection status */
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+ tBTA_HL_MDEP_ID local_mdep_id;
+ tBTA_HL_MDL_ID mdl_id; /* MCAP data link ID for this
+ data channel conenction */
+ tBTA_HL_DCH_MODE dch_mode; /* data channel mode - reliable or streaming*/
+ BOOLEAN first_reliable; /* whether this is the first reliable data channel */
+ UINT16 mtu;
+} tBTA_HL_DCH_OPEN_CFM;
+
+
+typedef struct
+{
+ BOOLEAN intentional;
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_DCH_CLOSE_IND;
+
+
+typedef struct
+{
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_MDL_IND;
+
+typedef struct
+{
+ tBTA_HL_STATUS status;
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+} tBTA_HL_MDL_CFM;
+
+typedef struct
+{
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+ tBTA_HL_MDL_ID mdl_id;
+} tBTA_HL_DELETE_MDL_IND;
+
+typedef struct
+{
+ tBTA_HL_STATUS status;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+ tBTA_HL_MDL_ID mdl_id;
+} tBTA_HL_DELETE_MDL_CFM;
+
+typedef struct
+{
+ tBTA_HL_MDL_HANDLE mdl_handle;
+ tBTA_HL_MCL_HANDLE mcl_handle;
+ tBTA_HL_APP_HANDLE app_handle;
+ BOOLEAN cong;
+} tBTA_HL_DCH_CONG_IND;
+
+typedef struct
+{
+ tBTA_HL_APP_HANDLE app_handle;
+ UINT16 ctrl_psm;
+ UINT16 data_psm;
+ UINT8 data_x_spec;
+ UINT8 mcap_sup_procs;
+} tBTA_HL_SDP_INFO_IND;
+
+typedef struct
+{
+ tBTA_HL_STATUS status;
+ tBTA_HL_APP_HANDLE app_handle;
+ BD_ADDR bd_addr;
+ tBTA_HL_SDP *p_sdp;
+} tBTA_HL_SDP_QUERY_CFM;
+
+typedef union
+{
+ tBTA_HL_REGISTER_CFM reg_cfm;
+ tBTA_HL_DEREGISTER_CFM dereg_cfm;
+ tBTA_HL_CCH_OPEN_IND cch_open_ind;
+ tBTA_HL_CCH_OPEN_CFM cch_open_cfm;
+ tBTA_HL_CCH_CLOSE_IND cch_close_ind;
+ tBTA_HL_MCL_CFM cch_close_cfm;
+ tBTA_HL_DCH_CREATE_IND dch_create_ind;
+ tBTA_HL_DCH_OPEN_IND dch_open_ind;
+ tBTA_HL_DCH_OPEN_CFM dch_open_cfm;
+ tBTA_HL_DCH_CLOSE_IND dch_close_ind;
+ tBTA_HL_MDL_CFM dch_close_cfm;
+ tBTA_HL_DCH_OPEN_IND dch_reconnect_ind;
+ tBTA_HL_DCH_OPEN_CFM dch_reconnect_cfm;
+ tBTA_HL_MCL_IND dch_abort_ind;
+ tBTA_HL_MCL_CFM dch_abort_cfm;
+ tBTA_HL_DELETE_MDL_IND delete_mdl_ind;
+ tBTA_HL_DELETE_MDL_CFM delete_mdl_cfm;
+ tBTA_HL_MDL_CFM dch_send_data_cfm;
+ tBTA_HL_MDL_IND dch_rcv_data_ind;
+ tBTA_HL_DCH_CONG_IND dch_cong_ind;
+ tBTA_HL_MCL_CFM echo_test_cfm;
+ tBTA_HL_SDP_QUERY_CFM sdp_query_cfm;
+ tBTA_HL_SDP_INFO_IND sdp_info_ind;
+
+} tBTA_HL;
+
+/* HL callback functions */
+typedef void tBTA_HL_CTRL_CBACK(tBTA_HL_CTRL_EVT event, tBTA_HL_CTRL *p_data);
+typedef void tBTA_HL_CBACK(tBTA_HL_EVT event, tBTA_HL *p_data);
+
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************
+** API Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function BTA_HlEnable
+**
+** Description Enable the HL subsystems. This function must be
+** called before any other functions in the HL API are called.
+** When the enable operation is completed the callback function
+** will be called with an BTA_HL_CTRL_ENABLE_CFM_EVT event.
+**
+** Parameters p_cback - HL event call back function
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlEnable(tBTA_HL_CTRL_CBACK *p_ctrl_cback);
+/*******************************************************************************
+**
+** Function BTA_HlDisable
+**
+** Description Disable the HL subsystem.
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDisable(void);
+/*******************************************************************************
+**
+** Function BTA_HlRegister
+**
+** Description Register a HDP application
+**
+**
+** Parameters app_id - hdp application ID
+** p_reg_param - non-platform related parameters for the
+** HDP application
+** p_cback - HL event callback fucntion
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlRegister(UINT8 app_id,
+ tBTA_HL_REG_PARAM *p_reg_param,
+ tBTA_HL_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_HlDeregister
+**
+** Description Deregister an HDP application
+**
+** Parameters app_handle - Application handle
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDeregister(tBTA_HL_APP_HANDLE app_handle);
+
+/*******************************************************************************
+**
+** Function BTA_HlCchOpen
+**
+** Description Open a Control channel connection with the specified BD address
+** and the control PSM value is used to select which
+** HDP insatnce should be used in case the peer device support
+** multiple HDP instances.
+**
+**
+** Parameters app_handle - Application Handle
+** p_open_param - parameters for opening a control channel
+**
+** Returns void
+**
+** Note: If the control PSM value is zero then the first HDP
+** instance is used for the control channel setup
+*******************************************************************************/
+ BTA_API extern void BTA_HlCchOpen(tBTA_HL_APP_HANDLE app_handle,
+ tBTA_HL_CCH_OPEN_PARAM *p_open_param);
+
+/*******************************************************************************
+**
+** Function BTA_HlCchClose
+**
+** Description Close a Control channel connection with the specified MCL
+** handle
+**
+** Parameters mcl_handle - MCL handle
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlCchClose(tBTA_HL_MCL_HANDLE mcl_handle);
+
+/*******************************************************************************
+**
+** Function BTA_HlDchOpen
+**
+** Description Open a data channel connection with the specified DCH parameters
+**
+** Parameters mcl_handle - MCL handle
+** p_open_param - parameters for opening a data channel
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDchOpen(tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_DCH_OPEN_PARAM *p_open_param);
+/*******************************************************************************
+**
+** Function BTA_HlDchReconnect
+**
+** Description Reconnect a data channel with the specified MDL_ID
+**
+** Parameters mcl_handle - MCL handle
+*8 p_recon_param - parameters for reconnecting a data channel
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDchReconnect(tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_DCH_RECONNECT_PARAM *p_recon_param);
+/*******************************************************************************
+**
+** Function BTA_HlDchClose
+**
+** Description Close a data channel with the specified MDL handle
+**
+** Parameters mdl_handle - MDL handle
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDchClose(tBTA_HL_MDL_HANDLE mdl_handle);
+
+/*******************************************************************************
+**
+** Function BTA_HlDchAbort
+**
+** Description Abort the current data channel setup with the specified MCL
+** handle
+**
+** Parameters mcl_handle - MCL handle
+**
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDchAbort(tBTA_HL_MCL_HANDLE mcl_handle);
+
+/*******************************************************************************
+**
+** Function BTA_HlSendData
+**
+** Description Send an APDU to the peer device
+**
+** Parameters mdl_handle - MDL handle
+** pkt_size - size of the data packet to be sent
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlSendData(tBTA_HL_MDL_HANDLE mdl_handle,
+ UINT16 pkt_size);
+
+/*******************************************************************************
+**
+** Function BTA_HlDeleteMdl
+**
+** Description Delete the specified MDL_ID within the specified MCL handle
+**
+** Parameters mcl_handle - MCL handle
+** mdl_id - MDL ID
+**
+** Returns void
+**
+** note: If mdl_id = 0xFFFF then this means to delete all MDLs
+** and this value can only be used with DeleteMdl request only
+** not other requests
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDeleteMdl(tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_MDL_ID mdl_id );
+
+/*******************************************************************************
+**
+** Function BTA_HlDchEchoTest
+**
+** Description Initiate an echo test with the specified MCL handle
+**
+** Parameters mcl_handle - MCL handle
+*8 p_echo_test_param - parameters for echo testing
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDchEchoTest( tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_DCH_ECHO_TEST_PARAM *p_echo_test_param);
+
+/*******************************************************************************
+**
+** Function BTA_HlSdpQuery
+**
+** Description SDP query request for the specified BD address
+**
+** Parameters app_handle - application handle
+** bd_addr - BD address
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlSdpQuery(tBTA_HL_APP_HANDLE app_handle,
+ BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_HlDchCreateMdlRsp
+**
+** Description Set the Response and configuration values for the Create MDL
+** request
+**
+** Parameters mcl_handle - MCL handle
+** p_rsp_param - parameters specified whether the request should
+** be accepted or not and if it should be accepted
+** then it also specified the configuration response
+** value
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_HlDchCreateRsp(tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_DCH_CREATE_RSP_PARAM *p_rsp_param);
+
+
+
+#ifdef __cplusplus
+
+}
+#endif
+
+#endif /* BTA_HL_API_H */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bta/include/bta_hl_ci.h b/bta/include/bta_hl_ci.h
new file mode 100644
index 0000000..4d3951c
--- /dev/null
+++ b/bta/include/bta_hl_ci.h
@@ -0,0 +1,125 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for the HL (HeaLth device profile) subsystem
+ * call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_HL_CI_H
+#define BTA_HL_CI_H
+
+#include "bta_api.h"
+#include "bta_hl_api.h"
+
+
+/*****************************************************************************
+** Constants and Data Types
+*****************************************************************************/
+/**************************
+** Common Definitions
+***************************/
+/* Read Ready Event */
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+/**************************
+** Common Functions
+***************************/
+/*******************************************************************************
+**
+** Function bta_hl_ci_get_tx_data
+**
+** Description This function is called in response to the
+** bta_hl_co_get_tx_data call-out function.
+**
+** Parameters mdl_handle -MDL handle
+** status - BTA_MA_STATUS_OK if operation is successful
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_get_tx_data( tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_STATUS status,
+ UINT16 evt );
+
+/*******************************************************************************
+**
+** Function bta_hl_ci_put_rx_data
+**
+** Description This function is called in response to the
+** bta_hl_co_put_rx_data call-out function.
+**
+** Parameters mdl_handle -MDL handle
+** status - BTA_MA_STATUS_OK if operation is successful
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_put_rx_data( tBTA_HL_MDL_HANDLE mdl_handle,
+ tBTA_HL_STATUS status,
+ UINT16 evt );
+
+
+
+/*******************************************************************************
+**
+** Function bta_hl_ci_get_echo_data
+**
+** Description This function is called in response to the
+** bta_hl_co_get_echo_data call-out function.
+**
+** Parameters mcl_handle -MCL handle
+** status - BTA_MA_STATUS_OK if operation is successful
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_get_echo_data( tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status,
+ UINT16 evt );
+
+
+/*******************************************************************************
+**
+** Function bta_hl_ci_put_echo_data
+**
+** Description This function is called in response to the
+** bta_hl_co_put_echo_data call-out function.
+**
+** Parameters mcl_handle -MCL handle
+** status - BTA_MA_STATUS_OK if operation is successful
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_put_echo_data( tBTA_HL_MCL_HANDLE mcl_handle,
+ tBTA_HL_STATUS status,
+ UINT16 evt );
+#endif /* BTA_HL_CI_H */
+
+
diff --git a/bta/include/bta_hl_co.h b/bta/include/bta_hl_co.h
new file mode 100644
index 0000000..46f8290
--- /dev/null
+++ b/bta/include/bta_hl_co.h
@@ -0,0 +1,232 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for the HL (HeaLth device profile) subsystem
+ * call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_HL_CO_H
+#define BTA_HL_CO_H
+
+#include "bta_api.h"
+#include "bta_hl_api.h"
+
+/*****************************************************************************
+** Constants and Data Types
+*****************************************************************************/
+/**************************
+** Common Definitions
+***************************/
+
+
+/*******************************************************************************
+**
+** Function bta_hl_co_get_num_of_mdep
+**
+** Description This function is called to get the number of MDEPs for this
+** application ID
+**
+** Parameters app_id - application ID
+** p_num_of_mdep (output) - number of MDEP configurations supported
+** by the application
+**
+** Returns Bloolean - TRUE success
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_get_num_of_mdep(UINT8 app_id, UINT8 *p_num_of_mdep);
+/*******************************************************************************
+**
+** Function bta_hl_co_advrtise_source_sdp
+**
+** Description This function is called to find out whether the SOURCE MDEP
+** configuration information should be advertize in the SDP or nopt
+**
+** Parameters app_id - application ID
+**
+** Returns Bloolean - TRUE advertise the SOURCE MDEP configuration
+** information
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_advrtise_source_sdp(UINT8 app_id);
+/*******************************************************************************
+**
+** Function bta_hl_co_get_mdep_config
+**
+** Description This function is called to get the supported feature
+** configuration for the specified mdep index and it also assigns
+** the MDEP ID for the specified mdep index
+**
+** Parameters app_id - HDP application ID
+** mdep_idx - the mdep index
+** mdep_id - the assigned MDEP ID for the specified medp_idx
+** p_mdl_cfg (output) - pointer to the MDEP configuration
+**
+**
+** Returns Bloolean - TRUE success
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_get_mdep_config(UINT8 app_id,
+ UINT8 mdep_idx,
+ tBTA_HL_MDEP_ID mdep_id,
+ tBTA_HL_MDEP_CFG *p_mdep_cfg);
+
+
+/*******************************************************************************
+**
+** Function bta_hl_co_get_echo_config
+**
+** Description This function is called to get the echo test
+** maximum APDU size configuration
+**
+** Parameters app_id - HDP application ID
+** p_echo_cfg (output) - pointer to the Echo test maximum APDU size
+** configuration
+**
+** Returns Bloolean - TRUE success
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_get_echo_config(UINT8 app_id,
+ tBTA_HL_ECHO_CFG *p_echo_cfg);
+
+
+/*******************************************************************************
+**
+** Function bta_hl_co_save_mdl
+**
+** Description This function is called to save a MDL configuration item in persistent
+** storage
+**
+** Parameters app_id - HDP application ID
+** item_idx - the MDL configuration storage index
+** p_mdl_cfg - pointer to the MDL configuration data
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_save_mdl(UINT8 app_id, UINT8 item_idx, tBTA_HL_MDL_CFG *p_mdl_cfg );
+/*******************************************************************************
+**
+** Function bta_hl_co_delete_mdl
+**
+** Description This function is called to delete a MDL configuration item in persistent
+** storage
+**
+** Parameters app_id - HDP application ID
+** item_idx - the MDL configuration storage index
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_delete_mdl(UINT8 app_id, UINT8 item_idx);
+/*******************************************************************************
+**
+** Function bta_hl_co_get_mdl_config
+**
+** Description This function is called to get the MDL configuration
+** from teh persistent memory. This function shall only be called
+*8 once after the device is powered up
+**
+** Parameters app_id - HDP application ID
+** buffer_size - the unit of the buffer size is sizeof(tBTA_HL_MDL_CFG)
+** p_mdl_buf - Point to the starting location of the buffer
+**
+** Returns BOOLEAN
+**
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_load_mdl_config (UINT8 app_id, UINT8 buffer_size,
+ tBTA_HL_MDL_CFG *p_mdl_buf );
+
+
+/*******************************************************************************
+**
+** Function bta_hl_co_get_tx_data
+**
+** Description Get the data to be sent
+**
+** Parameters app_id - HDP application ID
+** mdl_handle - MDL handle
+** buf_size - the size of the buffer
+** p_buf - the buffer pointer
+** evt - the evt to be passed back to the HL in the
+** bta_hl_ci_get_tx_data call-in function
+**
+** Returns Void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_get_tx_data (UINT8 app_id, tBTA_HL_MDL_HANDLE mdl_handle,
+ UINT16 buf_size, UINT8 *p_buf, UINT16 evt);
+
+
+/*******************************************************************************
+**
+** Function bta_hl_co_put_rx_data
+**
+** Description Put the received data
+**
+** Parameters app_id - HDP application ID
+** mdl_handle - MDL handle
+** data_size - the size of the data
+** p_data - the data pointer
+** evt - the evt to be passed back to the HL in the
+** bta_hl_ci_put_rx_data call-in function
+**
+** Returns Void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_put_rx_data (UINT8 app_id, tBTA_HL_MDL_HANDLE mdl_handle,
+ UINT16 data_size, UINT8 *p_data, UINT16 evt);
+/*******************************************************************************
+**
+** Function bta_hl_co_get_tx_data
+**
+** Description Get the Echo data to be sent
+**
+** Parameters app_id - HDP application ID
+** mcl_handle - MCL handle
+** buf_size - the size of the buffer
+** p_buf - the buffer pointer
+** evt - the evt to be passed back to the HL in the
+** bta_hl_ci_get_tx_data call-in function
+**
+** Returns Void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_get_echo_data (UINT8 app_id, tBTA_HL_MCL_HANDLE mcl_handle,
+ UINT16 buf_size, UINT8 *p_buf, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function bta_hl_co_put_echo_data
+**
+** Description Put the received loopback echo data
+**
+** Parameters app_id - HDP application ID
+** mcl_handle - MCL handle
+** data_size - the size of the data
+** p_data - the data pointer
+** evt - the evt to be passed back to the HL in the
+** bta_hl_ci_put_echo_data call-in function
+**
+** Returns Void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_put_echo_data (UINT8 app_id, tBTA_HL_MCL_HANDLE mcl_handle,
+ UINT16 data_size, UINT8 *p_data, UINT16 evt);
+
+#endif /* BTA_HL_CO_H */
diff --git a/bta/include/bta_jv_api.h b/bta/include/bta_jv_api.h
new file mode 100644
index 0000000..73a9164
--- /dev/null
+++ b/bta/include/bta_jv_api.h
@@ -0,0 +1,1122 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file the BTA Java I/F
+ *
+ ******************************************************************************/
+#ifndef BTA_JV_API_H
+#define BTA_JV_API_H
+
+#include "data_types.h"
+#include "bt_target.h"
+#include "bt_types.h"
+#include "bta_api.h"
+#include "btm_api.h"
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+/* status values */
+#define BTA_JV_SUCCESS 0 /* Successful operation. */
+#define BTA_JV_FAILURE 1 /* Generic failure. */
+#define BTA_JV_BUSY 2 /* Temporarily can not handle this request. */
+#define BTA_JV_NO_DATA 3 /* no data. */
+
+typedef UINT8 tBTA_JV_STATUS;
+#define BTA_JV_INTERNAL_ERR (-1) /* internal error. */
+
+#define BTA_JV_MAX_UUIDS SDP_MAX_UUID_FILTERS
+#define BTA_JV_MAX_ATTRS SDP_MAX_ATTR_FILTERS
+#define BTA_JV_MAX_SDP_REC SDP_MAX_RECORDS
+#if SDP_FOR_JV_INCLUDED == TRUE
+#define BTA_JV_MAX_L2C_CONN (GAP_MAX_CONNECTIONS + 1)
+#else
+#define BTA_JV_MAX_L2C_CONN GAP_MAX_CONNECTIONS
+#endif
+#define BTA_JV_MAX_SCN PORT_MAX_RFC_PORTS /* same as BTM_MAX_SCN (in btm_int.h) */
+#define BTA_JV_MAX_RFC_CONN MAX_RFC_PORTS
+
+#ifndef BTA_JV_DEF_RFC_MTU
+#define BTA_JV_DEF_RFC_MTU (3*330)
+#endif
+
+/* */
+#ifndef BTA_JV_MAX_RFC_SR_SESSION
+#define BTA_JV_MAX_RFC_SR_SESSION 3
+#endif
+
+/* BTA_JV_MAX_RFC_SR_SESSION can not be bigger than MAX_BD_CONNECTIONS */
+#if (BTA_JV_MAX_RFC_SR_SESSION > MAX_BD_CONNECTIONS)
+#undef BTA_JV_MAX_RFC_SR_SESSION
+#define BTA_JV_MAX_RFC_SR_SESSION MAX_BD_CONNECTIONS
+#endif
+
+#define BTA_JV_FIRST_SERVICE_ID BTA_FIRST_JV_SERVICE_ID
+#define BTA_JV_LAST_SERVICE_ID BTA_LAST_JV_SERVICE_ID
+#define BTA_JV_NUM_SERVICE_ID (BTA_LAST_JV_SERVICE_ID - BTA_FIRST_JV_SERVICE_ID + 1)
+
+/* Discoverable modes */
+enum
+{
+ BTA_JV_DISC_NONE,
+ BTA_JV_DISC_LIMITED,
+ BTA_JV_DISC_GENERAL
+};
+typedef UINT16 tBTA_JV_DISC;
+
+/* Security Mode (BTA_JvGetSecurityMode) */
+#define BTA_JV_SEC_MODE_UNDEFINED BTM_SEC_MODE_UNDEFINED /* 0 */
+#define BTA_JV_SEC_MODE_NONE BTM_SEC_MODE_NONE /* 1 */
+#define BTA_JV_SEC_MODE_SERVICE BTM_SEC_MODE_SERVICE /* 2 */
+#define BTA_JV_SEC_MODE_LINK BTM_SEC_MODE_LINK /* 3 */
+#define BTA_JV_SEC_MODE_SP BTM_SEC_MODE_SP /* 4 */
+#define BTA_JV_SEC_MODE_SP_DEBUG BTM_SEC_MODE_SP_DEBUG /* 5 */
+typedef UINT8 tBTA_JV_SEC_MODE;
+
+#define BTA_JV_ROLE_SLAVE BTM_ROLE_SLAVE
+#define BTA_JV_ROLE_MASTER BTM_ROLE_MASTER
+typedef UINT32 tBTA_JV_ROLE;
+
+#define BTA_JV_SERVICE_LMTD_DISCOVER BTM_COD_SERVICE_LMTD_DISCOVER /* 0x0020 */
+#define BTA_JV_SERVICE_POSITIONING BTM_COD_SERVICE_POSITIONING /* 0x0100 */
+#define BTA_JV_SERVICE_NETWORKING BTM_COD_SERVICE_NETWORKING /* 0x0200 */
+#define BTA_JV_SERVICE_RENDERING BTM_COD_SERVICE_RENDERING /* 0x0400 */
+#define BTA_JV_SERVICE_CAPTURING BTM_COD_SERVICE_CAPTURING /* 0x0800 */
+#define BTA_JV_SERVICE_OBJ_TRANSFER BTM_COD_SERVICE_OBJ_TRANSFER /* 0x1000 */
+#define BTA_JV_SERVICE_AUDIO BTM_COD_SERVICE_AUDIO /* 0x2000 */
+#define BTA_JV_SERVICE_TELEPHONY BTM_COD_SERVICE_TELEPHONY /* 0x4000 */
+#define BTA_JV_SERVICE_INFORMATION BTM_COD_SERVICE_INFORMATION /* 0x8000 */
+
+
+
+/* Java I/F callback events */
+/* events received by tBTA_JV_DM_CBACK */
+#define BTA_JV_ENABLE_EVT 0 /* JV enabled */
+#define BTA_JV_SET_DISCOVER_EVT 1 /* the result for BTA_JvSetDiscoverability */
+#define BTA_JV_LOCAL_ADDR_EVT 2 /* Local device address */
+#define BTA_JV_LOCAL_NAME_EVT 3 /* Local device name */
+#define BTA_JV_REMOTE_NAME_EVT 4 /* Remote device name */
+#define BTA_JV_SET_ENCRYPTION_EVT 5 /* Set Encryption */
+#define BTA_JV_GET_SCN_EVT 6 /* Reserved an SCN */
+#define BTA_JV_GET_PSM_EVT 7 /* Reserved a PSM */
+#define BTA_JV_DISCOVERY_COMP_EVT 8 /* SDP discovery complete */
+#define BTA_JV_SERVICES_LEN_EVT 9 /* the result for BTA_JvGetServicesLength */
+#define BTA_JV_SERVICE_SEL_EVT 10 /* the result for BTA_JvServiceSelect */
+#define BTA_JV_CREATE_RECORD_EVT 11 /* the result for BTA_JvCreateRecord */
+#define BTA_JV_UPDATE_RECORD_EVT 12 /* the result for BTA_JvUpdateRecord */
+#define BTA_JV_ADD_ATTR_EVT 13 /* the result for BTA_JvAddAttribute */
+#define BTA_JV_DELETE_ATTR_EVT 14 /* the result for BTA_JvDeleteAttribute */
+#define BTA_JV_CANCEL_DISCVRY_EVT 15 /* the result for BTA_JvCancelDiscovery */
+
+/* events received by tBTA_JV_L2CAP_CBACK */
+#define BTA_JV_L2CAP_OPEN_EVT 16 /* open status of L2CAP connection */
+#define BTA_JV_L2CAP_CLOSE_EVT 17 /* L2CAP connection closed */
+#define BTA_JV_L2CAP_START_EVT 18 /* L2CAP server started */
+#define BTA_JV_L2CAP_CL_INIT_EVT 19 /* L2CAP client initiated a connection */
+#define BTA_JV_L2CAP_DATA_IND_EVT 20 /* L2CAP connection received data */
+#define BTA_JV_L2CAP_CONG_EVT 21 /* L2CAP connection congestion status changed */
+#define BTA_JV_L2CAP_READ_EVT 22 /* the result for BTA_JvL2capRead */
+#define BTA_JV_L2CAP_RECEIVE_EVT 23 /* the result for BTA_JvL2capReceive*/
+#define BTA_JV_L2CAP_WRITE_EVT 24 /* the result for BTA_JvL2capWrite*/
+
+/* events received by tBTA_JV_RFCOMM_CBACK */
+#define BTA_JV_RFCOMM_OPEN_EVT 25 /* open status of RFCOMM Client connection */
+#define BTA_JV_RFCOMM_CLOSE_EVT 26 /* RFCOMM connection closed */
+#define BTA_JV_RFCOMM_START_EVT 27 /* RFCOMM server started */
+#define BTA_JV_RFCOMM_CL_INIT_EVT 28 /* RFCOMM client initiated a connection */
+#define BTA_JV_RFCOMM_DATA_IND_EVT 29 /* RFCOMM connection received data */
+#define BTA_JV_RFCOMM_CONG_EVT 30 /* RFCOMM connection congestion status changed */
+#define BTA_JV_RFCOMM_READ_EVT 31 /* the result for BTA_JvRfcommRead */
+#define BTA_JV_RFCOMM_WRITE_EVT 32 /* the result for BTA_JvRfcommWrite*/
+#define BTA_JV_RFCOMM_SRV_OPEN_EVT 33 /* open status of Server RFCOMM connection */
+#define BTA_JV_MAX_EVT 34 /* max number of JV events */
+
+typedef UINT16 tBTA_JV_EVT;
+
+/* data associated with BTA_JV_SET_DISCOVER_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ tBTA_JV_DISC disc_mode; /* The current discoverable mode */
+} tBTA_JV_SET_DISCOVER;
+
+/* data associated with BTA_JV_DISCOVERY_COMP_EVT_ */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ int scn; /* channel # */
+} tBTA_JV_DISCOVERY_COMP;
+
+/* data associated with BTA_JV_SET_ENCRYPTION_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ BD_ADDR bd_addr; /* The peer address */
+} tBTA_JV_SET_ENCRYPTION;
+
+/* data associated with BTA_JV_SERVICES_LEN_EVT */
+typedef struct
+{
+ INT32 num_services; /* -1, if error. Otherwise, the number of
+ * services collected from peer */
+ UINT16 *p_services_len; /* this points the same location as the
+ * parameter in BTA_JvGetServicesLength() */
+} tBTA_JV_SERVICES_LEN;
+
+/* data associated with BTA_JV_SERVICE_SEL_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* The peer address */
+ UINT16 service_len; /* the length of this record */
+} tBTA_JV_SERVICE_SEL;
+
+/* data associated with BTA_JV_CREATE_RECORD_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+} tBTA_JV_CREATE_RECORD;
+
+/* data associated with BTA_JV_UPDATE_RECORD_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The SDP record handle was updated */
+} tBTA_JV_UPDATE_RECORD;
+
+/* data associated with BTA_JV_ADD_ATTR_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The SDP record handle was updated */
+} tBTA_JV_ADD_ATTR;
+
+/* data associated with BTA_JV_DELETE_ATTR_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The SDP record handle was updated */
+} tBTA_JV_DELETE_ATTR;
+
+/* data associated with BTA_JV_L2CAP_OPEN_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ BD_ADDR rem_bda; /* The peer address */
+ INT32 tx_mtu; /* The transmit MTU */
+} tBTA_JV_L2CAP_OPEN;
+
+/* data associated with BTA_JV_L2CAP_CLOSE_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ BOOLEAN async; /* FALSE, if local initiates disconnect */
+} tBTA_JV_L2CAP_CLOSE;
+
+/* data associated with BTA_JV_L2CAP_START_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT8 sec_id; /* security ID used by this server */
+} tBTA_JV_L2CAP_START;
+
+/* data associated with BTA_JV_L2CAP_CL_INIT_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT8 sec_id; /* security ID used by this client */
+} tBTA_JV_L2CAP_CL_INIT;
+
+/* data associated with BTA_JV_L2CAP_CONG_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ BOOLEAN cong; /* TRUE, congested. FALSE, uncongested */
+} tBTA_JV_L2CAP_CONG;
+
+/* data associated with BTA_JV_L2CAP_READ_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT32 req_id; /* The req_id in the associated BTA_JvL2capRead() */
+ UINT8 *p_data; /* This points the same location as the p_data
+ * parameter in BTA_JvL2capRead () */
+ UINT16 len; /* The length of the data read. */
+} tBTA_JV_L2CAP_READ;
+
+/* data associated with BTA_JV_L2CAP_RECEIVE_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT32 req_id; /* The req_id in the associated BTA_JvL2capReceive() */
+ UINT8 *p_data; /* This points the same location as the p_data
+ * parameter in BTA_JvL2capReceive () */
+ UINT16 len; /* The length of the data read. */
+} tBTA_JV_L2CAP_RECEIVE;
+
+/* data associated with BTA_JV_L2CAP_WRITE_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT32 req_id; /* The req_id in the associated BTA_JvL2capWrite() */
+ UINT16 len; /* The length of the data written. */
+ BOOLEAN cong; /* congestion status */
+} tBTA_JV_L2CAP_WRITE;
+
+/* data associated with BTA_JV_RFCOMM_OPEN_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ BD_ADDR rem_bda; /* The peer address */
+} tBTA_JV_RFCOMM_OPEN;
+/* data associated with BTA_JV_RFCOMM_SRV_OPEN_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT32 new_listen_handle; /* The new listen handle */
+ BD_ADDR rem_bda; /* The peer address */
+} tBTA_JV_RFCOMM_SRV_OPEN;
+
+
+/* data associated with BTA_JV_RFCOMM_CLOSE_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 port_status; /* PORT status */
+ UINT32 handle; /* The connection handle */
+ BOOLEAN async; /* FALSE, if local initiates disconnect */
+} tBTA_JV_RFCOMM_CLOSE;
+
+/* data associated with BTA_JV_RFCOMM_START_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT8 sec_id; /* security ID used by this server */
+ BOOLEAN use_co; /* TRUE to use co_rfc_data */
+} tBTA_JV_RFCOMM_START;
+
+/* data associated with BTA_JV_RFCOMM_CL_INIT_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT8 sec_id; /* security ID used by this client */
+ BOOLEAN use_co; /* TRUE to use co_rfc_data */
+} tBTA_JV_RFCOMM_CL_INIT;
+/*data associated with BTA_JV_L2CAP_DATA_IND_EVT & BTA_JV_RFCOMM_DATA_IND_EVT */
+typedef struct
+{
+ UINT32 handle; /* The connection handle */
+} tBTA_JV_DATA_IND;
+
+/* data associated with BTA_JV_RFCOMM_CONG_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ BOOLEAN cong; /* TRUE, congested. FALSE, uncongested */
+} tBTA_JV_RFCOMM_CONG;
+
+/* data associated with BTA_JV_RFCOMM_READ_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT32 req_id; /* The req_id in the associated BTA_JvRfcommRead() */
+ UINT8 *p_data; /* This points the same location as the p_data
+ * parameter in BTA_JvRfcommRead () */
+ UINT16 len; /* The length of the data read. */
+} tBTA_JV_RFCOMM_READ;
+
+/* data associated with BTA_JV_RFCOMM_WRITE_EVT */
+typedef struct
+{
+ tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
+ UINT32 handle; /* The connection handle */
+ UINT32 req_id; /* The req_id in the associated BTA_JvRfcommWrite() */
+ int len; /* The length of the data written. */
+ BOOLEAN cong; /* congestion status */
+} tBTA_JV_RFCOMM_WRITE;
+
+
+/* union of data associated with JV callback */
+typedef union
+{
+ tBTA_JV_STATUS status; /* BTA_JV_ENABLE_EVT */
+ tBTA_JV_DISCOVERY_COMP disc_comp; /* BTA_JV_DISCOVERY_COMP_EVT */
+ tBTA_JV_SET_DISCOVER set_discover; /* BTA_JV_SET_DISCOVER_EVT */
+ tBTA_JV_SET_ENCRYPTION set_encrypt; /* BTA_JV_SET_ENCRYPTION_EVT */
+ BD_ADDR bd_addr; /* BTA_JV_LOCAL_ADDR_EVT */
+ UINT8 *p_name; /* BTA_JV_LOCAL_NAME_EVT,
+ BTA_JV_REMOTE_NAME_EVT */
+ UINT8 scn; /* BTA_JV_GET_SCN_EVT */
+ UINT16 psm; /* BTA_JV_GET_PSM_EVT */
+ tBTA_JV_SERVICES_LEN servs_len; /* BTA_JV_SERVICES_LEN_EVT */
+ tBTA_JV_SERVICE_SEL serv_sel; /* BTA_JV_SERVICE_SEL_EVT */
+ tBTA_JV_CREATE_RECORD create_rec; /* BTA_JV_CREATE_RECORD_EVT */
+ tBTA_JV_UPDATE_RECORD update_rec; /* BTA_JV_UPDATE_RECORD_EVT */
+ tBTA_JV_ADD_ATTR add_attr; /* BTA_JV_ADD_ATTR_EVT */
+ tBTA_JV_DELETE_ATTR del_attr; /* BTA_JV_DELETE_ATTR_EVT */
+ tBTA_JV_L2CAP_OPEN l2c_open; /* BTA_JV_L2CAP_OPEN_EVT */
+ tBTA_JV_L2CAP_CLOSE l2c_close; /* BTA_JV_L2CAP_CLOSE_EVT */
+ tBTA_JV_L2CAP_START l2c_start; /* BTA_JV_L2CAP_START_EVT */
+ tBTA_JV_L2CAP_CL_INIT l2c_cl_init; /* BTA_JV_L2CAP_CL_INIT_EVT */
+ tBTA_JV_L2CAP_CONG l2c_cong; /* BTA_JV_L2CAP_CONG_EVT */
+ tBTA_JV_L2CAP_READ l2c_read; /* BTA_JV_L2CAP_READ_EVT */
+ tBTA_JV_L2CAP_WRITE l2c_write; /* BTA_JV_L2CAP_WRITE_EVT */
+ tBTA_JV_RFCOMM_OPEN rfc_open; /* BTA_JV_RFCOMM_OPEN_EVT */
+ tBTA_JV_RFCOMM_SRV_OPEN rfc_srv_open; /* BTA_JV_RFCOMM_SRV_OPEN_EVT */
+ tBTA_JV_RFCOMM_CLOSE rfc_close; /* BTA_JV_RFCOMM_CLOSE_EVT */
+ tBTA_JV_RFCOMM_START rfc_start; /* BTA_JV_RFCOMM_START_EVT */
+ tBTA_JV_RFCOMM_CL_INIT rfc_cl_init; /* BTA_JV_RFCOMM_CL_INIT_EVT */
+ tBTA_JV_RFCOMM_CONG rfc_cong; /* BTA_JV_RFCOMM_CONG_EVT */
+ tBTA_JV_RFCOMM_READ rfc_read; /* BTA_JV_RFCOMM_READ_EVT */
+ tBTA_JV_RFCOMM_WRITE rfc_write; /* BTA_JV_RFCOMM_WRITE_EVT */
+ tBTA_JV_DATA_IND data_ind; /* BTA_JV_L2CAP_DATA_IND_EVT
+ BTA_JV_RFCOMM_DATA_IND_EVT */
+} tBTA_JV;
+
+/* JAVA DM Interface callback */
+typedef void (tBTA_JV_DM_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data, void * user_data);
+
+/* JAVA RFCOMM interface callback */
+typedef void* (tBTA_JV_RFCOMM_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data);
+
+/* JAVA L2CAP interface callback */
+typedef void (tBTA_JV_L2CAP_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data);
+
+/* JV configuration structure */
+typedef struct
+{
+ UINT16 sdp_raw_size; /* The size of p_sdp_raw_data */
+ UINT16 sdp_db_size; /* The size of p_sdp_db */
+ UINT8 *p_sdp_raw_data; /* The data buffer to keep raw data */
+ tSDP_DISCOVERY_DB *p_sdp_db; /* The data buffer to keep SDP database */
+} tBTA_JV_CFG;
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function BTA_JvEnable
+**
+** Description Enable the Java I/F service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_JV_ENABLE_EVT. This function must
+** be called before other functions in the JV API are
+** called.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_JvDisable
+**
+** Description Disable the Java I/F
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_JvDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_JvIsEnable
+**
+** Description Get the JV registration status.
+**
+** Returns TRUE, if registered
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsEnable(void);
+
+/*******************************************************************************
+**
+** Function BTA_JvSetDiscoverability
+**
+** Description This function sets the Bluetooth discoverable modes
+** of the local device. This controls whether other
+** Bluetooth devices can find the local device.
+**
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_SET_DISCOVER_EVT.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvSetDiscoverability(tBTA_JV_DISC disc_mode);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetDiscoverability
+**
+** Description This function gets the Bluetooth
+** discoverable modes of local device
+**
+** Returns The current Bluetooth discoverable mode.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_DISC BTA_JvGetDiscoverability(void);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetLocalDeviceAddr
+**
+** Description This function obtains the local Bluetooth device address.
+** The local Bluetooth device address is reported by the
+** tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_ADDR_EVT.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetLocalDeviceAddr(void);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetLocalDeviceName
+**
+** Description This function obtains the name of the local device
+** The local Bluetooth device name is reported by the
+** tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_NAME_EVT.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetLocalDeviceName(void);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetRemoteDeviceName
+**
+** Description This function obtains the name of the specified device.
+** The Bluetooth device name is reported by the
+** tBTA_JV_DM_CBACK callback with a BTA_JV_REMOTE_NAME_EVT.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetRemoteDeviceName(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetPreknownDevice
+**
+** Description This function obtains the Bluetooth address in the inquiry
+** database collected via the previous call to BTA_DmSearch().
+**
+** Returns The number of preknown devices if p_bd_addr is NULL
+** BTA_JV_SUCCESS if successful.
+** BTA_JV_INTERNAL_ERR(-1) if internal failure.
+**
+*******************************************************************************/
+BTA_API extern INT32 BTA_JvGetPreknownDevice(UINT8 * p_bd_addr, UINT32 index);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetDeviceClass
+**
+** Description This function obtains the local Class of Device.
+**
+** Returns DEV_CLASS, A three-byte array of UINT8 that contains the
+** Class of Device information. The definitions are in the
+** "Bluetooth Assigned Numbers".
+**
+*******************************************************************************/
+BTA_API extern UINT8 * BTA_JvGetDeviceClass(void);
+
+/*******************************************************************************
+**
+** Function BTA_JvSetServiceClass
+**
+** Description This function sets the service class of local Class of Device
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvSetServiceClass(UINT32 service);
+
+/*******************************************************************************
+**
+** Function BTA_JvSetEncryption
+**
+** Description This function ensures that the connection to the given device
+** is encrypted.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_SET_ENCRYPTION_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvSetEncryption(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_JvIsAuthenticated
+**
+** Description This function checks if the peer device is authenticated
+**
+** Returns TRUE if authenticated.
+** FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsAuthenticated(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_JvIsTrusted
+**
+** Description This function checks if the peer device is trusted
+** (previously paired)
+**
+** Returns TRUE if trusted.
+** FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsTrusted(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_JvIsAuthorized
+**
+** Description This function checks if the peer device is authorized
+**
+** Returns TRUE if authorized.
+** FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsAuthorized(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_JvIsEncrypted
+**
+** Description This function checks if the link to peer device is encrypted
+**
+** Returns TRUE if encrypted.
+** FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsEncrypted(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetSecurityMode
+**
+** Description This function returns the current Bluetooth security mode
+** of the local device
+**
+** Returns The current Bluetooth security mode.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_SEC_MODE BTA_JvGetSecurityMode(void);
+
+/* BTA_JvIsMaster is replaced by BTA_DmIsMaster */
+
+/*******************************************************************************
+**
+** Function BTA_JvGetSCN
+**
+** Description This function reserves a SCN (server channel number) for
+** applications running over RFCOMM. It is primarily called by
+** server profiles/applications to register their SCN into the
+** SDP database. The SCN is reported by the tBTA_JV_DM_CBACK
+** callback with a BTA_JV_GET_SCN_EVT.
+** If the SCN reported is 0, that means all SCN resources are
+** exhausted.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetSCN(void);
+
+/*******************************************************************************
+**
+** Function BTA_JvFreeSCN
+**
+** Description This function frees a server channel number that was used
+** by an application running over RFCOMM.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvFreeSCN(UINT8 scn);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetPSM
+**
+** Description This function reserves a PSM (Protocol Service Multiplexer)
+** applications running over L2CAP. It is primarily called by
+** server profiles/applications to register their PSM into the
+** SDP database.
+**
+** Returns The next free PSM
+**
+*******************************************************************************/
+BTA_API extern UINT16 BTA_JvGetPSM(void);
+
+/*******************************************************************************
+**
+** Function BTA_JvStartDiscovery
+**
+** Description This function performs service discovery for the services
+** provided by the given peer device. When the operation is
+** complete the tBTA_JV_DM_CBACK callback function will be
+** called with a BTA_JV_DISCOVERY_COMP_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid,
+ tSDP_UUID *p_uuid_list, void* user_data);
+
+/*******************************************************************************
+**
+** Function BTA_JvCancelDiscovery
+**
+** Description This function cancels an active service discovery.
+** When the operation is
+** complete the tBTA_JV_DM_CBACK callback function will be
+** called with a BTA_JV_CANCEL_DISCVRY_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvCancelDiscovery(void * user_data);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetServicesLength
+**
+** Description This function obtains the number of services and the length
+** of each service found in the SDP database (result of last
+** BTA_JvStartDiscovery().When the operation is complete the
+** tBTA_JV_DM_CBACK callback function will be called with a
+** BTA_JV_SERVICES_LEN_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetServicesLength(BOOLEAN inc_hdr, UINT16 *p_services_len);
+
+/*******************************************************************************
+**
+** Function BTA_JvGetServicesResult
+**
+** Description This function returns a number of service records found
+** during current service search, equals to the number returned
+** by previous call to BTA_JvGetServicesLength.
+** The contents of each SDP record will be returned under a
+** TLV (type, len, value) representation in the data buffer
+** provided by the caller.
+**
+** Returns -1, if error. Otherwise, the number of services
+**
+*******************************************************************************/
+BTA_API extern INT32 BTA_JvGetServicesResult(BOOLEAN inc_hdr, UINT8 **TLVs);
+
+/*******************************************************************************
+**
+** Function BTA_JvServiceSelect
+**
+** Description This function checks if the SDP database contains the given
+** service UUID. When the operation is complete the
+** tBTA_JV_DM_CBACK callback function will be called with a
+** BTA_JV_SERVICE_SEL_EVT with the length of the service record.
+** If the service is not found or error, -1 is reported.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvServiceSelect(UINT16 uuid);
+
+/*******************************************************************************
+**
+** Function BTA_JvServiceResult
+**
+** Description This function returns the contents of the SDP record from
+** last BTA_JvServiceSelect. The contents will be returned under
+** a TLV (type, len, value) representation in the data buffer
+** provided by the caller.
+**
+** Returns -1, if error. Otherwise, the length of service record.
+**
+*******************************************************************************/
+BTA_API extern INT32 BTA_JvServiceResult(UINT8 *TLV);
+
+/*******************************************************************************
+**
+** Function BTA_JvCreateRecord
+**
+** Description Create a service record in the local SDP database by user in
+** tBTA_JV_DM_CBACK callback with a BTA_JV_CREATE_RECORD_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvCreateRecordByUser(void* user_data);
+
+/*******************************************************************************
+**
+** Function BTA_JvUpdateRecord
+**
+** Description Update a service record in the local SDP database.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_UPDATE_RECORD_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvUpdateRecord(UINT32 handle, UINT16 *p_ids,
+ UINT8 **p_values, INT32 *p_value_sizes, INT32 array_len);
+
+/*******************************************************************************
+**
+** Function BTA_JvAddAttribute
+**
+** Description Add an attribute to a service record in the local SDP database.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_ADD_ATTR_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvAddAttribute(UINT32 handle, UINT16 attr_id,
+ UINT8 *p_value, INT32 value_size);
+
+/*******************************************************************************
+**
+** Function BTA_JvDeleteAttribute
+**
+** Description Delete an attribute from a service record in the local SDP database.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_DELETE_ATTR_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvDeleteAttribute(UINT32 handle, UINT16 attr_id);
+
+/*******************************************************************************
+**
+** Function BTA_JvDeleteRecord
+**
+** Description Delete a service record in the local SDP database.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvDeleteRecord(UINT32 handle);
+
+/*******************************************************************************
+**
+** Function BTA_JvReadRecord
+**
+** Description Read a service record in the local SDP database.
+**
+** Returns -1, if the record is not found.
+** Otherwise, the offset (0 or 1) to start of data in p_data.
+**
+** The size of data copied into p_data is in *p_data_len.
+**
+*******************************************************************************/
+BTA_API extern INT32 BTA_JvReadRecord(UINT32 handle, UINT8 *p_data, INT32 *p_data_len);
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capConnect
+**
+** Description Initiate a connection as a L2CAP client to the given BD
+** Address.
+** When the connection is initiated or failed to initiate,
+** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_CL_INIT_EVT
+** When the connection is established or failed,
+** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capConnect(tBTA_SEC sec_mask,
+ tBTA_JV_ROLE role, UINT16 remote_psm, UINT16 rx_mtu,
+ BD_ADDR peer_bd_addr, tBTA_JV_L2CAP_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capClose
+**
+** Description This function closes an L2CAP client connection
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capClose(UINT32 handle);
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capStartServer
+**
+** Description This function starts an L2CAP server and listens for an L2CAP
+** connection from a remote Bluetooth device. When the server
+** is started successfully, tBTA_JV_L2CAP_CBACK is called with
+** BTA_JV_L2CAP_START_EVT. When the connection is established,
+** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capStartServer(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ UINT16 local_psm, UINT16 rx_mtu,
+ tBTA_JV_L2CAP_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capStopServer
+**
+** Description This function stops the L2CAP server. If the server has an
+** active connection, it would be closed.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capStopServer(UINT16 local_psm);
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capRead
+**
+** Description This function reads data from an L2CAP connection
+** When the operation is complete, tBTA_JV_L2CAP_CBACK is
+** called with BTA_JV_L2CAP_READ_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capRead(UINT32 handle, UINT32 req_id,
+ UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capReceive
+**
+** Description This function reads data from an L2CAP connection
+** When the operation is complete, tBTA_JV_L2CAP_CBACK is
+** called with BTA_JV_L2CAP_RECEIVE_EVT.
+** If there are more data queued in L2CAP than len, the extra data will be discarded.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capReceive(UINT32 handle, UINT32 req_id,
+ UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capReady
+**
+** Description This function determined if there is data to read from
+** an L2CAP connection
+**
+** Returns BTA_JV_SUCCESS, if data queue size is in *p_data_size.
+** BTA_JV_FAILURE, if error.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capReady(UINT32 handle, UINT32 *p_data_size);
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capWrite
+**
+** Description This function writes data to an L2CAP connection
+** When the operation is complete, tBTA_JV_L2CAP_CBACK is
+** called with BTA_JV_L2CAP_WRITE_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capWrite(UINT32 handle, UINT32 req_id,
+ UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommConnect
+**
+** Description This function makes an RFCOMM conection to a remote BD
+** Address.
+** When the connection is initiated or failed to initiate,
+** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CL_INIT_EVT
+** When the connection is established or failed,
+** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_OPEN_EVT
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask,
+ tBTA_JV_ROLE role, UINT8 remote_scn, BD_ADDR peer_bd_addr,
+ tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data);
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommClose
+**
+** Description This function closes an RFCOMM connection
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle);
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommStartServer
+**
+** Description This function starts listening for an RFCOMM connection
+** request from a remote Bluetooth device. When the server is
+** started successfully, tBTA_JV_RFCOMM_CBACK is called
+** with BTA_JV_RFCOMM_START_EVT.
+** When the connection is established, tBTA_JV_RFCOMM_CBACK
+** is called with BTA_JV_RFCOMM_OPEN_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask,
+ tBTA_JV_ROLE role, UINT8 local_scn, UINT8 max_session,
+ tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data);
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommStopServer
+**
+** Description This function stops the RFCOMM server. If the server has an
+** active connection, it would be closed.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommStopServer(UINT32 handle);
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommRead
+**
+** Description This function reads data from an RFCOMM connection
+** When the operation is complete, tBTA_JV_RFCOMM_CBACK is
+** called with BTA_JV_RFCOMM_READ_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommRead(UINT32 handle, UINT32 req_id,
+ UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommReady
+**
+** Description This function determined if there is data to read from
+** an RFCOMM connection
+**
+** Returns BTA_JV_SUCCESS, if data queue size is in *p_data_size.
+** BTA_JV_FAILURE, if error.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommReady(UINT32 handle, UINT32 *p_data_size);
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommWrite
+**
+** Description This function writes data to an RFCOMM connection
+** When the operation is complete, tBTA_JV_RFCOMM_CBACK is
+** called with BTA_JV_RFCOMM_WRITE_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id);
+
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommGetPortHdl
+**
+** Description This function fetches the rfcomm port handle
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_JV_API_H */
+
diff --git a/bta/include/bta_jv_co.h b/bta/include/bta_jv_co.h
new file mode 100644
index 0000000..098766c
--- /dev/null
+++ b/bta/include/bta_jv_co.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2007-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for java interface call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_JV_CO_H
+#define BTA_JV_CO_H
+
+#include "bta_jv_api.h"
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+
+/*******************************************************************************
+**
+** Function bta_jv_co_rfc_data
+**
+** Description This function is called by JV to send data to the java glue
+** code when the RX data path is configured to use a call-out
+**
+** Returns void
+**
+*******************************************************************************/
+
+BTA_API extern int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf);
+BTA_API extern int bta_co_rfc_data_outgoing_size(void *user_data, int *size);
+BTA_API extern int bta_co_rfc_data_outgoing(void *user_data, UINT8* buf, UINT16 size);
+
+#endif /* BTA_DG_CO_H */
+
diff --git a/bta/include/bta_op_api.h b/bta/include/bta_op_api.h
new file mode 100644
index 0000000..c26ea35
--- /dev/null
+++ b/bta/include/bta_op_api.h
@@ -0,0 +1,67 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the object push (OP) client and
+ * server subsystem of BTA, Broadcom's Bluetooth application layer for
+ * mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_OP_API_H
+#define BTA_OP_API_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+/* Extra Debug Code */
+#ifndef BTA_OPS_DEBUG
+#define BTA_OPS_DEBUG FALSE
+#endif
+
+#ifndef BTA_OPC_DEBUG
+#define BTA_OPC_DEBUG FALSE
+#endif
+
+
+/* Object format */
+#define BTA_OP_VCARD21_FMT 1 /* vCard 2.1 */
+#define BTA_OP_VCARD30_FMT 2 /* vCard 3.0 */
+#define BTA_OP_VCAL_FMT 3 /* vCal 1.0 */
+#define BTA_OP_ICAL_FMT 4 /* iCal 2.0 */
+#define BTA_OP_VNOTE_FMT 5 /* vNote */
+#define BTA_OP_VMSG_FMT 6 /* vMessage */
+#define BTA_OP_OTHER_FMT 0xFF /* other format */
+
+typedef UINT8 tBTA_OP_FMT;
+
+/* Object format mask */
+#define BTA_OP_VCARD21_MASK 0x01 /* vCard 2.1 */
+#define BTA_OP_VCARD30_MASK 0x02 /* vCard 3.0 */
+#define BTA_OP_VCAL_MASK 0x04 /* vCal 1.0 */
+#define BTA_OP_ICAL_MASK 0x08 /* iCal 2.0 */
+#define BTA_OP_VNOTE_MASK 0x10 /* vNote */
+#define BTA_OP_VMSG_MASK 0x20 /* vMessage */
+#define BTA_OP_ANY_MASK 0x40 /* Any type of object. */
+
+typedef UINT8 tBTA_OP_FMT_MASK;
+
+#endif /* BTA_OP_API_H */
+
diff --git a/bta/include/bta_pan_api.h b/bta/include/bta_pan_api.h
new file mode 100644
index 0000000..2166766
--- /dev/null
+++ b/bta/include/bta_pan_api.h
@@ -0,0 +1,201 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the Personal Area Networking (PAN)
+ * subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ * phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_PAN_API_H
+#define BTA_PAN_API_H
+
+#include "bta_api.h"
+#include "pan_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+#define BTA_PAN_SUCCESS 0
+#define BTA_PAN_FAIL 1
+
+typedef UINT8 tBTA_PAN_STATUS;
+
+
+/* PAN Callback events */
+#define BTA_PAN_ENABLE_EVT 0 /* PAN service is enabled. */
+#define BTA_PAN_SET_ROLE_EVT 1 /* PAN roles registered */
+#define BTA_PAN_OPENING_EVT 2 /* Connection is being opened. */
+#define BTA_PAN_OPEN_EVT 3 /* Connection has been opened. */
+#define BTA_PAN_CLOSE_EVT 4 /* Connection has been closed. */
+
+typedef UINT8 tBTA_PAN_EVT;
+
+
+/* pan roles */
+#define BTA_PAN_ROLE_PANU PAN_ROLE_CLIENT
+#define BTA_PAN_ROLE_GN PAN_ROLE_GN_SERVER
+#define BTA_PAN_ROLE_NAP PAN_ROLE_NAP_SERVER
+
+
+typedef UINT8 tBTA_PAN_ROLE;
+
+/* information regarding PAN roles */
+typedef struct
+{
+ char *p_srv_name; /* service name for the PAN role */
+ UINT8 app_id; /* application id */
+ tBTA_SEC sec_mask; /* security setting for the role */
+
+} tBTA_PAN_ROLE_INFO;
+
+
+/* Event associated with BTA_PAN_SET_ROLE_EVT */
+typedef struct
+{
+ tBTA_PAN_STATUS status; /* status of set role event */
+ tBTA_PAN_ROLE role; /* PAN roles successfully registered */
+} tBTA_PAN_SET_ROLE;
+
+/* Event associated with BTA_PAN_OPENING_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address of peer device. */
+ UINT16 handle; /* Handle associated with this connection. */
+
+} tBTA_PAN_OPENING;
+
+
+/* Event associated with BTA_PAN_OPEN_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address of peer device. */
+ UINT16 handle; /* Handle associated with this connection. */
+ tBTA_PAN_STATUS status; /* status of open event */
+ tBTA_PAN_ROLE local_role; /* Local device PAN role for the connection */
+ tBTA_PAN_ROLE peer_role; /* Peer device PAN role for the connection */
+
+} tBTA_PAN_OPEN;
+
+/* Event associated with BTA_PAN_CLOSE_EVT */
+typedef struct
+{
+ UINT16 handle; /* Handle associated with the connection. */
+} tBTA_PAN_CLOSE;
+
+/* Union of all PAN callback structures */
+typedef union
+{
+ tBTA_PAN_SET_ROLE set_role; /* set_role event */
+ tBTA_PAN_OPEN open; /* Connection has been opened. */
+ tBTA_PAN_OPENING opening; /* Connection being opened */
+ tBTA_PAN_CLOSE close; /* Connection has been closed. */
+} tBTA_PAN;
+
+/* Number of PAN connections */
+#ifndef BTA_PAN_NUM_CONN
+#define BTA_PAN_NUM_CONN 4
+#endif
+
+/* PAN callback */
+typedef void (tBTA_PAN_CBACK)(tBTA_PAN_EVT event, tBTA_PAN *p_data);
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+BTA_API extern void BTA_PanEnable(tBTA_PAN_CBACK p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_PanDisable
+**
+** Description Disable PAN service.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PanDisable(void);
+
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+BTA_API 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);
+
+
+/*******************************************************************************
+**
+** 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);
+
+
+
+/*******************************************************************************
+**
+** Function BTA_PanClose
+**
+** Description Close a PAN connection to a peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PanClose(UINT16 handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_PAN_API_H */
+
diff --git a/bta/include/bta_pan_ci.h b/bta/include/bta_pan_ci.h
new file mode 100644
index 0000000..faeef54
--- /dev/null
+++ b/bta/include/bta_pan_ci.h
@@ -0,0 +1,151 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for pan call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_PAN_CI_H
+#define BTA_PAN_CI_H
+
+#include "bta_pan_api.h"
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_tx_ready(UINT16 handle);
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_rx_ready(UINT16 handle);
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_tx_flow(UINT16 handle, BOOLEAN enable);
+
+/*******************************************************************************
+**
+** 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 TRUE if flow enabled
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_rx_writebuf(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf, BOOLEAN ext);
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_readbuf
+**
+** Description This function is called by the phone to read data from PAN
+** when the TX path is configured to use a pull interface.
+** The phone must free the buffer using function GKI_freebuf() when
+** it is through processing the buffer.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern BT_HDR * bta_pan_ci_readbuf(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 *p_protocol,
+ BOOLEAN* p_ext, BOOLEAN* p_forward);
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_set_pfilters
+**
+** Description This function is called to set protocol filters
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_set_pfilters(UINT16 handle, UINT16 num_filters, UINT16 *p_start_array, UINT16 *p_end_array);
+
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_set_mfilters
+**
+** Description This function is called to set multicast filters
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_set_mfilters(UINT16 handle, UINT16 num_mcast_filters, UINT8 *p_start_array,
+ UINT8 *p_end_array);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_PAN_CI_H */
+
diff --git a/bta/include/bta_pan_co.h b/bta/include/bta_pan_co.h
new file mode 100644
index 0000000..5b20fad
--- /dev/null
+++ b/bta/include/bta_pan_co.h
@@ -0,0 +1,201 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for data gateway call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_PAN_CO_H
+#define BTA_PAN_CO_H
+
+#include "bta_pan_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+
+
+/* BT_HDR buffer offset */
+#define BTA_PAN_MIN_OFFSET PAN_MINIMUM_OFFSET
+
+
+/* Data Flow Mask */
+#define BTA_PAN_RX_PUSH 0x00 /* RX push. */
+#define BTA_PAN_RX_PUSH_BUF 0x01 /* RX push with zero copy. */
+#define BTA_PAN_RX_PULL 0x02 /* RX pull. */
+#define BTA_PAN_TX_PUSH 0x00 /* TX push. */
+#define BTA_PAN_TX_PUSH_BUF 0x10 /* TX push with zero copy. */
+#define BTA_PAN_TX_PULL 0x20 /* TX pull. */
+
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_pan_co_init
+**
+** Description This callout function is executed by PAN when a server is
+** started by calling BTA_PanEnable(). This function can be
+** used by the phone to initialize data paths or for other
+** initialization purposes. The function must return the
+** data flow mask as described below.
+**
+**
+** Returns Data flow mask.
+**
+*******************************************************************************/
+BTA_API extern UINT8 bta_pan_co_init(UINT8 *q_level);
+
+/*******************************************************************************
+**
+** Function bta_pan_co_open
+**
+** Description This function is executed by PAN when a connection
+** is opened. The phone can use this function to set
+** up data paths or perform any required initialization.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_open(UINT16 handle, UINT8 app_id, tBTA_PAN_ROLE local_role, tBTA_PAN_ROLE peer_role, BD_ADDR peer_addr);
+
+/*******************************************************************************
+**
+** Function bta_pan_co_close
+**
+** Description This function is called by PAN when a connection to a
+** server is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_close(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_pan_co_tx_path
+**
+** Description This function is called by PAN to transfer data on the
+** TX path; that is, data being sent from BTA to the phone.
+** This function is used when the TX data path is configured
+** to use the pull interface.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_tx_path(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_pan_co_rx_path
+**
+** Description This function is called by PAN to transfer data on the
+** RX path; that is, data being sent from the phone to BTA.
+** This function is used when the RX data path is configured
+** to use the pull interface.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_rx_path(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_pan_co_tx_write
+**
+** Description This function is called by PAN to send data to the phone
+** when the TX path is configured to use a push interface.
+** The implementation of this function must copy the data to
+** the phone's memory.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_tx_write(UINT16 handle, UINT8 app_id, BD_ADDR src, BD_ADDR dst, UINT16 protocol, UINT8 *p_data,
+ UINT16 len, BOOLEAN ext, BOOLEAN forward);
+
+/*******************************************************************************
+**
+** Function bta_pan_co_tx_writebuf
+**
+** Description This function is called by PAN to send data to the phone
+** when the TX path is configured to use a push interface with
+** zero copy. The phone must free the buffer using function
+** GKI_freebuf() when it is through processing the buffer.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_tx_writebuf(UINT16 handle, UINT8 app_id, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf,
+ BOOLEAN ext, BOOLEAN forward);
+
+
+/*******************************************************************************
+**
+** Function bta_pan_co_rx_flow
+**
+** Description This function is called by PAN to enable or disable
+** data flow on the RX path when it is configured to use
+** a push interface. If data flow is disabled the phone must
+** not call bta_pan_ci_rx_write() or bta_pan_ci_rx_writebuf()
+** until data flow is enabled again.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_rx_flow(UINT16 handle, UINT8 app_id, BOOLEAN enable);
+
+
+/*******************************************************************************
+**
+** Function bta_pan_co_filt_ind
+**
+** Description protocol filter indication from peer device
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_pfilt_ind(UINT16 handle, BOOLEAN indication, tBTA_PAN_STATUS result,
+ UINT16 len, UINT8 *p_filters);
+
+/*******************************************************************************
+**
+** Function bta_pan_co_mfilt_ind
+**
+** Description multicast filter indication from peer device
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_mfilt_ind(UINT16 handle, BOOLEAN indication, tBTA_PAN_STATUS result,
+ UINT16 len, UINT8 *p_filters);
+
+#endif /* BTA_PAN_CO_H */
+
diff --git a/bta/include/bta_pbs_api.h b/bta/include/bta_pbs_api.h
new file mode 100644
index 0000000..c3563c2
--- /dev/null
+++ b/bta/include/bta_pbs_api.h
@@ -0,0 +1,49 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the phone book access (PB) server
+ * subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ * phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_PB_API_H
+#define BTA_PB_API_H
+
+#include "bta_api.h"
+#include "btm_api.h"
+#include "bta_sys.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/**************************
+** Common Definitions
+***************************/
+
+/* Profile supported features */
+#define BTA_PBS_SUPF_DOWNLOAD 0x0001
+#define BTA_PBS_SURF_BROWSE 0x0002
+
+/* Profile supported repositories */
+#define BTA_PBS_REPOSIT_LOCAL 0x01 /* Local PhoneBook */
+#define BTA_PBS_REPOSIT_SIM 0x02 /* SIM card PhoneBook */
+
+#endif
diff --git a/bta/include/bta_sys_ci.h b/bta/include/bta_sys_ci.h
new file mode 100644
index 0000000..4818386
--- /dev/null
+++ b/bta/include/bta_sys_ci.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for system call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_CI_H
+#define BTA_SYS_CI_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_ci_enabled
+**
+** Description This function must be called in response to function
+** bta_sys_hw_co_enable(), when HW is indeed enabled
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void bta_sys_hw_ci_enabled(tBTA_SYS_HW_MODULE module );
+
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_ci_disabled
+**
+** Description This function must be called in response to function
+** bta_sys_hw_co_disable() when HW is really OFF
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void bta_sys_hw_ci_disabled( tBTA_SYS_HW_MODULE module );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/bta/include/bta_sys_co.h b/bta/include/bta_sys_co.h
new file mode 100644
index 0000000..92118a3
--- /dev/null
+++ b/bta/include/bta_sys_co.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the interface file for system callout functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_CO_H
+#define BTA_SYS_CO_H
+
+#include "bta_sys.h"
+
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_co_enable
+**
+** Description This function is called by the stack to power up the HW
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void bta_sys_hw_co_enable( tBTA_SYS_HW_MODULE module );
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_co_disable
+**
+** Description This function is called by the stack to power down the HW
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void bta_sys_hw_co_disable( tBTA_SYS_HW_MODULE module );
+
+
+#endif
diff --git a/bta/include/ptim.h b/bta/include/ptim.h
new file mode 100644
index 0000000..80e50bd
--- /dev/null
+++ b/bta/include/ptim.h
@@ -0,0 +1,99 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Protocol timer services.
+ *
+ ******************************************************************************/
+#ifndef PTIM_H
+#define PTIM_H
+
+#include "gki.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+typedef struct
+{
+ TIMER_LIST_Q timer_queue; /* GKI timer queue */
+ INT32 period; /* Timer period in milliseconds */
+ UINT32 last_gki_ticks; /* GKI ticks since last time update called */
+ UINT8 timer_id; /* GKI timer id */
+} tPTIM_CB;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function ptim_init
+**
+** Description Initialize a protocol timer service control block.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void ptim_init(tPTIM_CB *p_cb, UINT16 period, UINT8 timer_id);
+
+/*******************************************************************************
+**
+** Function ptim_timer_update
+**
+** Description Update the protocol timer list and handle expired timers.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void ptim_timer_update(tPTIM_CB *p_cb);
+
+/*******************************************************************************
+**
+** Function ptim_start_timer
+**
+** Description Start a protocol timer for the specified amount
+** of time in milliseconds.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void ptim_start_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout);
+
+/*******************************************************************************
+**
+** Function ptim_stop_timer
+**
+** Description Stop a protocol timer.
+**
+** Returns void
+**
+*******************************************************************************/
+extern void ptim_stop_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PTIM_H */
diff --git a/bta/include/utl.h b/bta/include/utl.h
new file mode 100644
index 0000000..df08b5a
--- /dev/null
+++ b/bta/include/utl.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Basic utility functions.
+ *
+ ******************************************************************************/
+#ifndef UTL_H
+#define UTL_H
+
+#include "data_types.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+/*** class of device settings ***/
+#define BTA_UTL_SET_COD_MAJOR_MINOR 0x01
+#define BTA_UTL_SET_COD_SERVICE_CLASS 0x02 /* only set the bits in the input */
+#define BTA_UTL_CLR_COD_SERVICE_CLASS 0x04
+#define BTA_UTL_SET_COD_ALL 0x08 /* take service class as the input (may clear some set bits!!) */
+#define BTA_UTL_INIT_COD 0x0a
+
+/*****************************************************************************
+** Type Definitions
+*****************************************************************************/
+
+/** for utl_set_device_class() **/
+typedef struct
+{
+ UINT8 minor;
+ UINT8 major;
+ UINT16 service;
+} tBTA_UTL_COD;
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function utl_str2int
+**
+** Description This utility function converts a character string to an
+** integer. Acceptable values in string are 0-9. If invalid
+** string or string value too large, -1 is returned.
+**
+**
+** Returns Integer value or -1 on error.
+**
+*******************************************************************************/
+extern INT16 utl_str2int(const char *p_s);
+
+/*******************************************************************************
+**
+** Function utl_strucmp
+**
+** Description This utility function compares two strings in uppercase.
+** String p_s must be uppercase. String p_t is converted to
+** uppercase if lowercase. If p_s ends first, the substring
+** match is counted as a match.
+**
+**
+** Returns 0 if strings match, nonzero otherwise.
+**
+*******************************************************************************/
+extern int utl_strucmp(const char *p_s, const char *p_t);
+
+/*******************************************************************************
+**
+** Function utl_itoa
+**
+** Description This utility function converts a UINT16 to a string. The
+** string is NULL-terminated. The length of the string is
+** returned.
+**
+**
+** Returns Length of string.
+**
+*******************************************************************************/
+extern UINT8 utl_itoa(UINT16 i, char *p_s);
+
+/*******************************************************************************
+**
+** Function utl_freebuf
+**
+** Description This function calls GKI_freebuf to free the buffer passed
+** in, if buffer pointer is not NULL, and also initializes
+** buffer pointer to NULL.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+extern void utl_freebuf(void **p);
+
+/*******************************************************************************
+**
+** Function utl_set_device_class
+**
+** Description This function updates the local Device Class.
+**
+** Parameters:
+** p_cod - Pointer to the device class to set to
+**
+** cmd - the fields of the device class to update.
+** BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+** BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in the input
+** BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in the input
+** BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class
+** BTA_UTL_INIT_COD - overwrite major, minor, and service class
+**
+** Returns TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_set_device_class(tBTA_UTL_COD *p_cod, UINT8 cmd);
+
+/*******************************************************************************
+**
+** Function utl_isintstr
+**
+** Description This utility function checks if the given string is an
+** integer string or not
+**
+**
+** Returns TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_isintstr(const char *p_s);
+
+/*******************************************************************************
+**
+** Function utl_isdialstr
+**
+** Description This utility function checks if the given string contains
+** only dial digits or not
+**
+**
+** Returns TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_isdialstr(const char *p_s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UTL_H */
diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c
new file mode 100644
index 0000000..77d18d9
--- /dev/null
+++ b/bta/jv/bta_jv_act.c
@@ -0,0 +1,2360 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains action functions for advanced audio.
+ *
+ ******************************************************************************/
+
+#include <hardware/bluetooth.h>
+#include <arpa/inet.h>
+
+#include "bt_types.h"
+#include "gki.h"
+#include "bd.h"
+#include "utl.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_jv_api.h"
+#include "bta_jv_int.h"
+#include "bta_jv_co.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include "sdp_api.h"
+#include "l2c_api.h"
+#include "port_api.h"
+#include <string.h>
+#include "rfcdefs.h"
+#include "avct_api.h"
+#include "avdt_api.h"
+
+
+#include <cutils/log.h>
+#define info(fmt, ...) ALOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define debug(fmt, ...) ALOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define error(fmt, ...) ALOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__)
+#define asrt(s) if(!(s)) ALOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
+
+
+
+#define HDL2CB(handle) \
+ UINT32 __hi = ((handle) & BTA_JV_RFC_HDL_MASK) - 1; \
+ UINT32 __si = BTA_JV_RFC_HDL_TO_SIDX(handle); \
+ tBTA_JV_RFC_CB *p_cb = &bta_jv_cb.rfc_cb[__hi]; \
+ tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[__si] - 1]
+
+extern void uuid_to_string(bt_uuid_t *p_uuid, char *str);
+static inline void logu(const char* title, const uint8_t * p_uuid)
+{
+ char uuids[128];
+ uuid_to_string((bt_uuid_t*)p_uuid, uuids);
+ ALOGD("%s: %s", title, uuids);
+}
+
+
+static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb);
+
+/*******************************************************************************
+**
+** Function bta_jv_get_local_device_addr_cback
+**
+** Description Callback from btm after local bdaddr is read
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_get_local_device_addr_cback(BD_ADDR bd_addr)
+{
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_LOCAL_ADDR_EVT, (tBTA_JV *)bd_addr, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_get_remote_device_name_cback
+**
+** Description Callback from btm after remote name is read
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_get_remote_device_name_cback(tBTM_REMOTE_DEV_NAME *p_name)
+{
+ tBTA_JV evt_data;
+ evt_data.p_name = p_name->remote_bd_name;
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_REMOTE_NAME_EVT, &evt_data, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_alloc_sec_id
+**
+** Description allocate a security id
+**
+** Returns
+**
+*******************************************************************************/
+UINT8 bta_jv_alloc_sec_id(void)
+{
+ UINT8 ret = 0;
+ int i;
+ for(i=0; i<BTA_JV_NUM_SERVICE_ID; i++)
+ {
+ if(0 == bta_jv_cb.sec_id[i])
+ {
+ bta_jv_cb.sec_id[i] = BTA_JV_FIRST_SERVICE_ID + i;
+ ret = bta_jv_cb.sec_id[i];
+ break;
+ }
+ }
+ return ret;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_free_sec_id
+**
+** Description free the given security id
+**
+** Returns
+**
+*******************************************************************************/
+static void bta_jv_free_sec_id(UINT8 *p_sec_id)
+{
+ UINT8 sec_id = *p_sec_id;
+ *p_sec_id = 0;
+ if(sec_id >= BTA_JV_FIRST_SERVICE_ID && sec_id <= BTA_JV_LAST_SERVICE_ID)
+ {
+ BTM_SecClrService(sec_id);
+ bta_jv_cb.sec_id[sec_id - BTA_JV_FIRST_SERVICE_ID] = 0;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_alloc_rfc_cb
+**
+** Description allocate a control block for the given port handle
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_RFC_CB * bta_jv_alloc_rfc_cb(UINT16 port_handle, tBTA_JV_PCB **pp_pcb)
+{
+ tBTA_JV_RFC_CB *p_cb = NULL;
+ tBTA_JV_PCB *p_pcb;
+ int i;
+ for(i=0; i<BTA_JV_MAX_RFC_CONN; i++)
+ {
+ if(0 == bta_jv_cb.rfc_cb[i].handle )
+ {
+ p_cb = &bta_jv_cb.rfc_cb[i];
+ p_cb->handle = i + 1;
+ p_cb->max_sess = 1;
+ p_cb->rfc_hdl[0] = port_handle;
+ APPL_TRACE_DEBUG2( "bta_jv_alloc_rfc_cb port_handle:%d handle:%d",
+ port_handle, p_cb->handle);
+ p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
+ p_pcb->handle = p_cb->handle;
+ p_pcb->port_handle = port_handle;
+ *pp_pcb = p_pcb;
+ break;
+ }
+ }
+ return p_cb;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_rfc_port_to_pcb
+**
+** Description find the port control block associated with the given port handle
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_PCB * bta_jv_rfc_port_to_pcb(UINT16 port_handle)
+{
+ tBTA_JV_PCB *p_pcb = NULL;
+
+ if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS) && bta_jv_cb.port_cb[port_handle - 1].handle)
+ {
+ p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
+ }
+
+ return p_pcb;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_rfc_port_to_cb
+**
+** Description find the RFCOMM control block associated with the given port handle
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_RFC_CB * bta_jv_rfc_port_to_cb(UINT16 port_handle)
+{
+ tBTA_JV_RFC_CB *p_cb = NULL;
+ UINT32 handle;
+
+ if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS) && bta_jv_cb.port_cb[port_handle - 1].handle)
+ {
+ handle = bta_jv_cb.port_cb[port_handle - 1].handle;
+ handle &= BTA_JV_RFC_HDL_MASK;
+ if (handle)
+ p_cb = &bta_jv_cb.rfc_cb[handle - 1];
+ }
+ return p_cb;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_free_rfc_pcb
+**
+** Description free the given port control block
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_STATUS bta_jv_free_rfc_pcb(tBTA_JV_PCB *p_pcb)
+{
+ tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+ BOOLEAN remove = FALSE;
+ BOOLEAN is_server = TRUE;
+ UINT16 port_handle;
+
+ APPL_TRACE_DEBUG2( "bta_jv_free_rfc_pcb handle:%d s:%d", p_pcb->port_handle, p_pcb->state);
+
+ if (p_pcb->port_handle)
+ {
+ if(BTA_JV_ST_NONE != p_pcb->state)
+ {
+ remove = TRUE;
+ if(p_pcb->state <= BTA_JV_ST_CL_MAX)
+ is_server = FALSE;
+ port_handle = p_pcb->port_handle;
+ }
+ p_pcb->port_handle = 0;
+ p_pcb->state = BTA_JV_ST_NONE;
+
+ //Initialize congestion flags
+ p_pcb->cong = FALSE;
+
+ if(remove)
+ {
+ if(is_server)
+ {
+ if(RFCOMM_RemoveServer(port_handle) != PORT_SUCCESS)
+ status = BTA_JV_FAILURE;
+ }
+ else
+ {
+ if(RFCOMM_RemoveConnection(port_handle) != PORT_SUCCESS)
+ status = BTA_JV_FAILURE;
+ }
+ }
+ }
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_free_rfc_cb
+**
+** Description free the given RFCOMM control block
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb)
+{
+ tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+ UINT8 i;
+ APPL_TRACE_DEBUG1( "bta_jv_free_rfc_cb max_sess:%d", p_cb->max_sess);
+ for (i=0; i<p_cb->max_sess; i++)
+ {
+ APPL_TRACE_DEBUG2( "[%d]: port=%d", i, p_cb->rfc_hdl[i]);
+ if (p_cb->rfc_hdl[i])
+ bta_jv_free_rfc_pcb (&bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1]);
+ }
+
+ p_cb->scn = 0;
+ bta_jv_free_sec_id(&p_cb->sec_id);
+ p_cb->p_cback = NULL;
+ p_cb->handle = 0;
+
+ return status;
+}
+static tBTA_JV_STATUS bta_jv_free_rfc_listen_cb(tBTA_JV_RFC_CB *p_cb)
+{
+ tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+ UINT8 i;
+ debug( "max_sess:%d", p_cb->max_sess);
+ for (i=0; i<p_cb->max_sess; i++)
+ {
+ APPL_TRACE_DEBUG2( "[%d]: port=%d", i, p_cb->rfc_hdl[i]);
+ if (p_cb->rfc_hdl[i])
+ {
+ tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
+ if(p_pcb->state == BTA_JV_ST_SR_LISTEN)
+ {
+ debug( "free listen pcb: scn:%d, ueser_data:%d", p_cb->scn, (int)p_pcb->user_data);
+ p_pcb->user_data = 0;
+ bta_jv_free_rfc_pcb (p_pcb);
+ p_cb->max_sess = 1;
+ break;
+ }
+ }
+ }
+ //p_cb->scn = 0;
+ bta_jv_free_sec_id(&p_cb->sec_id);
+ //p_cb->p_cback = NULL;
+ //p_cb->handle = 0;
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_free_l2c_cb
+**
+** Description free the given L2CAP control block
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB *p_cb)
+{
+#if 0
+ tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+
+ if(BTA_JV_ST_NONE != p_cb->state)
+ {
+#if SDP_FOR_JV_INCLUDED == TRUE
+ if(BTA_JV_L2C_FOR_SDP_HDL == p_cb->handle)
+ {
+ bta_jv_cb.sdp_data_size = 0;
+ if(SDP_ConnClose(bta_jv_cb.sdp_for_jv))
+ {
+ bta_jv_cb.sdp_for_jv = 0;
+ }
+ else
+ status = BTA_JV_FAILURE;
+ }
+ else
+#endif
+ if(GAP_ConnClose(p_cb->handle) != BT_PASS)
+ status = BTA_JV_FAILURE;
+ }
+ p_cb->psm = 0;
+ p_cb->state = BTA_JV_ST_NONE;
+ bta_jv_free_sec_id(&p_cb->sec_id);
+ p_cb->p_cback = NULL;
+ return status;
+#endif
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_alloc_sdp_id
+**
+** Description allocate a SDP id for the given SDP record handle
+**
+** Returns
+**
+*******************************************************************************/
+UINT32 bta_jv_alloc_sdp_id(UINT32 sdp_handle)
+{
+ int j;
+ UINT32 id = 0;
+
+ /* find a free entry */
+ for (j = 0; j < BTA_JV_MAX_SDP_REC; j++)
+ {
+ if (bta_jv_cb.sdp_handle[j] == 0)
+ {
+ bta_jv_cb.sdp_handle[j] = sdp_handle;
+ id = (UINT32)(j + 1);
+ break;
+ }
+ }
+ /* the SDP record handle reported is the (index + 1) to control block */
+ return id;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_free_sdp_id
+**
+** Description free the sdp id
+**
+** Returns
+**
+*******************************************************************************/
+void bta_jv_free_sdp_id(UINT32 sdp_id)
+{
+ if(sdp_id > 0 && sdp_id <= BTA_JV_MAX_SDP_REC)
+ {
+ bta_jv_cb.sdp_handle[sdp_id - 1] = 0;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_get_sdp_handle
+**
+** Description find the SDP handle associated with the given sdp id
+**
+** Returns
+**
+*******************************************************************************/
+UINT32 bta_jv_get_sdp_handle(UINT32 sdp_id)
+{
+ UINT32 sdp_handle = 0;
+
+ if(sdp_id > 0 && sdp_id <= BTA_JV_MAX_SDP_REC)
+ {
+ sdp_handle = bta_jv_cb.sdp_handle[sdp_id - 1];
+ }
+ return sdp_handle;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_check_psm
+**
+** Description for now use only the legal PSM per JSR82 spec
+**
+** Returns TRUE, if allowed
+**
+*******************************************************************************/
+BOOLEAN bta_jv_check_psm(UINT16 psm)
+{
+ BOOLEAN ret = FALSE;
+
+ if(L2C_IS_VALID_PSM(psm) )
+ {
+ if(psm < 0x1001)
+ {
+ /* see if this is defined by spec */
+ switch(psm)
+ {
+ case SDP_PSM: /* 1 */
+ case BT_PSM_RFCOMM: /* 3 */
+ /* do not allow java app to use these 2 PSMs */
+ break;
+
+ case TCS_PSM_INTERCOM: /* 5 */
+ case TCS_PSM_CORDLESS: /* 7 */
+ if( FALSE == bta_sys_is_register(BTA_ID_CT) &&
+ FALSE == bta_sys_is_register(BTA_ID_CG) )
+ ret = TRUE;
+ break;
+
+ case BT_PSM_BNEP: /* F */
+ if(FALSE == bta_sys_is_register(BTA_ID_PAN))
+ ret = TRUE;
+ break;
+
+ case HID_PSM_CONTROL: /* 0x11 */
+ case HID_PSM_INTERRUPT: /* 0x13 */
+ //FIX: allow HID Device and HID Host to coexist
+ if( FALSE == bta_sys_is_register(BTA_ID_HD) ||
+ FALSE == bta_sys_is_register(BTA_ID_HH) )
+ ret = TRUE;
+ break;
+
+ case AVCT_PSM: /* 0x17 */
+ case AVDT_PSM: /* 0x19 */
+ if ((FALSE == bta_sys_is_register(BTA_ID_AV)) &&
+ (FALSE == bta_sys_is_register(BTA_ID_AVK)))
+ ret = TRUE;
+ break;
+
+ default:
+ ret = TRUE;
+ break;
+ }
+ }
+ else
+ ret = TRUE;
+ }
+ return ret;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_enable
+**
+** Description Initialises the JAVA I/F
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_enable(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+ bta_jv_cb.p_dm_cback = p_data->enable.p_cback;
+ bta_jv_cb.p_dm_cback(BTA_JV_ENABLE_EVT, (tBTA_JV *)&status, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_disable
+**
+** Description Disables the BT device manager
+** free the resources used by java
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_disable (tBTA_JV_MSG *p_data)
+{
+ int i;
+
+ bta_jv_cb.p_dm_cback = NULL;
+ /* delete the SDP records created by java apps */
+ for(i=0; i<BTA_JV_MAX_SDP_REC; i++)
+ {
+ if(bta_jv_cb.sdp_handle[i])
+ {
+ APPL_TRACE_DEBUG1( "delete SDP record: %d", bta_jv_cb.sdp_handle[i]);
+ SDP_DeleteRecord(bta_jv_cb.sdp_handle[i]);
+ bta_jv_cb.sdp_handle[i] = 0;
+ }
+ }
+
+ /* free the SCNs allocated by java apps */
+ for(i=0; i<BTA_JV_MAX_SCN; i++)
+ {
+ if(bta_jv_cb.scn[i])
+ {
+ APPL_TRACE_DEBUG1( "free scn: %d", (i+1));
+ BTM_FreeSCN((UINT8)(i+1));
+ bta_jv_cb.scn[i] = FALSE;
+ }
+ }
+
+ /* disconnect L2CAP connections */
+ for(i=0; i<BTA_JV_MAX_L2C_CONN; i++)
+ {
+ bta_jv_free_l2c_cb(&bta_jv_cb.l2c_cb[i]);
+ }
+
+ /* disconnect RFCOMM connections */
+ for(i=0; i<BTA_JV_MAX_RFC_CONN; i++)
+ {
+ bta_jv_free_rfc_cb(&bta_jv_cb.rfc_cb[i]);
+ }
+
+ /* free the service records allocated by java apps */
+ for(i=0; i<BTA_JV_NUM_SERVICE_ID; i++)
+ {
+ if(bta_jv_cb.sec_id[i])
+ {
+ BTM_SecClrService(bta_jv_cb.sec_id[i]);
+ bta_jv_cb.sec_id[i] = 0;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_set_discoverability
+**
+** Description Sets discoverability
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_set_discoverability (tBTA_JV_MSG *p_data)
+{
+ tBTA_JV evt_data;
+
+ evt_data.set_discover.status = BTA_JV_FAILURE;
+ /* initialize the default value for the event as the current mode */
+ evt_data.set_discover.disc_mode = BTM_ReadDiscoverability(NULL, NULL);
+
+ if(BTM_SUCCESS == BTM_SetDiscoverability((UINT8)p_data->set_discoverability.disc_mode, 0, 0))
+ {
+ evt_data.set_discover.status = BTA_JV_SUCCESS;
+ /* update the mode, after BTM_SetDiscoverability() is successful */
+ evt_data.set_discover.disc_mode = p_data->set_discoverability.disc_mode;
+ }
+
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_SET_DISCOVER_EVT, &evt_data, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_get_local_device_addr
+**
+** Description Reads the local Bluetooth device address
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_get_local_device_addr(tBTA_JV_MSG *p_data)
+{
+ BTM_ReadLocalDeviceAddr((tBTM_CMPL_CB *)bta_jv_get_local_device_addr_cback);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_get_local_device_name
+**
+** Description Reads the local Bluetooth device name
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_get_local_device_name(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV evt_data;
+ char *name;
+
+ BTM_ReadLocalDeviceName(&name);
+ evt_data.p_name = (UINT8*)name;
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_LOCAL_NAME_EVT, &evt_data, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_get_remote_device_name
+**
+** Description Reads the local Bluetooth device name
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_get_remote_device_name(tBTA_JV_MSG *p_data)
+{
+
+ BTM_ReadRemoteDeviceName(p_data->get_rmt_name.bd_addr,
+ (tBTM_CMPL_CB *)bta_jv_get_remote_device_name_cback);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_set_service_class
+**
+** Description update the service class field of device class
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_set_service_class (tBTA_JV_MSG *p_data)
+{
+ tBTA_UTL_COD cod;
+
+ /* set class of device */
+ /* BTA_JvSetServiceClass(UINT32 service) assumes that the service class passed to the API function as defined in the assigned number page.
+ For example: the object transfer bit is bit 20 of the 24-bit Class of device; the value of this bit is 0x00100000 (value 1)
+ Our btm_api.h defines this bit as #define BTM_COD_SERVICE_OBJ_TRANSFER 0x1000 // (value 2)
+ This reflects that the service class defined at btm is UINT16, which starts at bit 8 of the 24 bit Class of Device
+ The following statement converts from (value 1) into (value 2) */
+ cod.service = (p_data->set_service.service >> 8);
+ utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_sec_cback
+**
+** Description callback function to handle set encryption complete event
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_sec_cback (BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
+{
+ tBTA_JV_SET_ENCRYPTION set_enc;
+ if(bta_jv_cb.p_dm_cback)
+ {
+ bdcpy(set_enc.bd_addr, bd_addr);
+ set_enc.status = result;
+ if (result > BTA_JV_BUSY)
+ set_enc.status = BTA_JV_FAILURE;
+ bta_jv_cb.p_dm_cback(BTA_JV_SET_ENCRYPTION_EVT, (tBTA_JV *)&set_enc, 0);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_set_encryption
+**
+** Description Reads the local Bluetooth device name
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_set_encryption(tBTA_JV_MSG *p_data)
+{
+ BTM_SetEncryption(p_data->set_encrypt.bd_addr, bta_jv_sec_cback, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_get_scn
+**
+** Description obtain a free SCN
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_get_scn(tBTA_JV_MSG *p_data)
+{
+#if 0
+ UINT8 scn;
+ scn = BTM_AllocateSCN();
+ if(scn)
+ bta_jv_cb.scn[scn-1] = TRUE;
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_GET_SCN_EVT, (tBTA_JV *)&scn);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_free_scn
+**
+** Description free a SCN
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_free_scn(tBTA_JV_MSG *p_data)
+{
+ UINT8 scn = p_data->free_scn.scn;
+
+ if (scn > 0 && scn <= BTA_JV_MAX_SCN && bta_jv_cb.scn[scn-1])
+ {
+ /* this scn is used by JV */
+ bta_jv_cb.scn[scn-1] = FALSE;
+ BTM_FreeSCN(scn);
+ }
+}
+static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID* u)
+{
+ static uint8_t bt_base_uuid[] =
+ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
+
+ logu("in, uuid:", u);
+ debug("uuid len:%d", u->len);
+ if(u->len == 16)
+ {
+ if(memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) == 0)
+ {
+ tBT_UUID su;
+ memset(&su, 0, sizeof(su));
+ if(u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0)
+ {
+ su.len = 2;
+ uint16_t u16;
+ memcpy(&u16, &u->uu.uuid128[2], sizeof(u16));
+ su.uu.uuid16 = ntohs(u16);
+ debug("shorten to 16 bits uuid: %x", su.uu.uuid16);
+ }
+ else
+ {
+ su.len = 4;
+ uint32_t u32;
+ memcpy(&u32, &u->uu.uuid128[0], sizeof(u32));
+ su.uu.uuid32 = ntohl(u32);
+ debug("shorten to 32 bits uuid: %x", su.uu.uuid32);
+ }
+ return su;
+ }
+ }
+ debug("cannot shorten none-reserved 128 bits uuid");
+ return *u;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_start_discovery_cback
+**
+** Description Callback for Start Discovery
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_start_discovery_cback(UINT16 result, void * user_data)
+{
+ tBTA_JV_STATUS status;
+ UINT8 old_sdp_act = bta_jv_cb.sdp_active;
+
+ debug( "bta_jv_start_discovery_cback res: 0x%x", result);
+
+ bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
+ if(bta_jv_cb.p_dm_cback)
+ {
+ if (old_sdp_act == BTA_JV_SDP_ACT_CANCEL)
+ {
+ debug("BTA_JV_SDP_ACT_CANCEL");
+ status = BTA_JV_SUCCESS;
+ bta_jv_cb.p_dm_cback(BTA_JV_CANCEL_DISCVRY_EVT, (tBTA_JV *)&status, user_data);
+ }
+ else
+ {
+ tBTA_JV_DISCOVERY_COMP dcomp;
+ dcomp.scn = 0;
+ status = BTA_JV_FAILURE;
+ if (result == SDP_SUCCESS || result == SDP_DB_FULL)
+ {
+ tSDP_DISC_REC *p_sdp_rec = NULL;
+ tSDP_PROTOCOL_ELEM pe;
+ logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
+ tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
+ logu("shorten uuid:", su.uu.uuid128);
+ p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
+ debug("p_sdp_rec:%p", p_sdp_rec);
+ if(p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ dcomp.scn = (UINT8) pe.params[0];
+ status = BTA_JV_SUCCESS;
+ }
+ }
+
+ dcomp.status = status;
+ bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&dcomp, user_data);
+ }
+ //free sdp db
+ //utl_freebuf(&(p_bta_jv_cfg->p_sdp_db));
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_start_discovery
+**
+** Description Discovers services on a remote device
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_start_discovery(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ debug("in, sdp_active:%d", bta_jv_cb.sdp_active);
+ if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE)
+ {
+ /* SDP is still in progress */
+ status = BTA_JV_BUSY;
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
+ return;
+ }
+/*
+ if(p_data->start_discovery.num_uuid == 0)
+ {
+ p_data->start_discovery.num_uuid = 1;
+ p_data->start_discovery.uuid_list[0].len = 2;
+ p_data->start_discovery.uuid_list[0].uu.uuid16 = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+ }
+*/
+ /* init the database/set up the filter */
+ debug("call SDP_InitDiscoveryDb, p_data->start_discovery.num_uuid:%d",
+ p_data->start_discovery.num_uuid);
+ SDP_InitDiscoveryDb (p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size,
+ p_data->start_discovery.num_uuid, p_data->start_discovery.uuid_list, 0, NULL);
+
+ /* tell SDP to keep the raw data */
+ p_bta_jv_cfg->p_sdp_db->raw_data = p_bta_jv_cfg->p_sdp_raw_data;
+ p_bta_jv_cfg->p_sdp_db->raw_size = p_bta_jv_cfg->sdp_raw_size;
+
+ bta_jv_cb.p_sel_raw_data = 0;
+ bta_jv_cb.uuid = p_data->start_discovery.uuid_list[0];
+
+ bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_YES;
+ if (!SDP_ServiceSearchAttributeRequest2(p_data->start_discovery.bd_addr,
+ p_bta_jv_cfg->p_sdp_db,
+ bta_jv_start_discovery_cback, p_data->start_discovery.user_data))
+ {
+ bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
+ /* failed to start SDP. report the failure right away */
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
+ }
+ /*
+ else report the result when the cback is called
+ */
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_cancel_discovery
+**
+** Description Cancels an active discovery
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_cancel_discovery(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+ if (bta_jv_cb.sdp_active == BTA_JV_SDP_ACT_YES)
+ {
+ if (SDP_CancelServiceSearch (p_bta_jv_cfg->p_sdp_db))
+ {
+ bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_CANCEL;
+ return;
+ }
+ }
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_CANCEL_DISCVRY_EVT, (tBTA_JV *)&status, p_data->cancel_discovery.user_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_get_services_length
+**
+** Description Obtain the length of each record in the SDP DB.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_get_services_length(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_SERVICES_LEN evt_data;
+ UINT8 *p, *np, *op, type;
+ UINT32 raw_used, raw_cur;
+ UINT32 len;
+
+ evt_data.num_services = -1;
+ evt_data.p_services_len = p_data->get_services_length.p_services_len;
+ if(p_bta_jv_cfg->p_sdp_db->p_first_rec)
+ {
+ /* the database is valid */
+ evt_data.num_services = 0;
+ p = p_bta_jv_cfg->p_sdp_db->raw_data;
+ raw_used = p_bta_jv_cfg->p_sdp_db->raw_used;
+ while(raw_used && p)
+ {
+ op = p;
+ type = *p++;
+ np = sdpu_get_len_from_type(p, type, &len);
+ p = np + len;
+ raw_cur = p - op;
+ if(raw_used >= raw_cur)
+ {
+ raw_used -= raw_cur;
+ }
+ else
+ {
+ /* error. can not continue */
+ break;
+ }
+ if(p_data->get_services_length.inc_hdr)
+ {
+ evt_data.p_services_len[evt_data.num_services++] = len + np - op;
+ }
+ else
+ {
+ evt_data.p_services_len[evt_data.num_services++] = len;
+ }
+ } /* end of while */
+ }
+
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_SERVICES_LEN_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_service_select
+**
+** Description Obtain the length of given UUID in the SDP DB.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_service_select(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_SERVICE_SEL serv_sel;
+ tSDP_DISC_REC *p_rec, *p_tmp;
+ UINT8 *p, *np, *op, type;
+ UINT32 raw_used, raw_cur;
+ UINT32 len;
+
+ serv_sel.service_len = 0;
+ bta_jv_cb.p_sel_raw_data = 0;
+ p_rec = SDP_FindServiceInDb (p_bta_jv_cfg->p_sdp_db, p_data->service_select.uuid, NULL);
+ if(p_rec)
+ {
+ /* found the record in the database */
+ /* the database must be valid */
+ p = p_bta_jv_cfg->p_sdp_db->raw_data;
+ raw_used = p_bta_jv_cfg->p_sdp_db->raw_used;
+ p_tmp = p_bta_jv_cfg->p_sdp_db->p_first_rec;
+ while(raw_used && p && p_tmp)
+ {
+ op = p;
+ type = *p++;
+ np = sdpu_get_len_from_type(p, type, &len);
+ if(p_tmp == p_rec)
+ {
+ bta_jv_cb.p_sel_raw_data = op;
+ bta_jv_cb.sel_len = len;
+ serv_sel.service_len = len;
+ bdcpy(serv_sel.bd_addr, p_rec->remote_bd_addr);
+ APPL_TRACE_DEBUG1( "bta_jv_service_select found uuid: 0x%x",
+ p_data->service_select.uuid);
+ break;
+ }
+ p = np + len;
+ raw_cur = p - op;
+ if(raw_used >= raw_cur)
+ {
+ raw_used -= raw_cur;
+ }
+ else
+ {
+ /* error. can not continue */
+ break;
+ }
+ p_tmp = p_tmp->p_next_rec;
+ } /* end of while */
+ }
+ APPL_TRACE_DEBUG1( "service_len: %d", serv_sel.service_len);
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_SERVICE_SEL_EVT, (tBTA_JV *)&serv_sel);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_create_record
+**
+** Description Create an SDP record with the given attributes
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_create_record(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_API_CREATE_RECORD *cr = &(p_data->create_record);
+ tBTA_JV_CREATE_RECORD evt_data;
+ evt_data.status = BTA_JV_SUCCESS;
+ if(bta_jv_cb.p_dm_cback)
+ //callback user immediately to create his own sdp record in stack thread context
+ bta_jv_cb.p_dm_cback(BTA_JV_CREATE_RECORD_EVT, (tBTA_JV *)&evt_data, cr->user_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_update_record
+**
+** Description Update an SDP record with the given attributes
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_update_record(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_API_UPDATE_RECORD *ur = &(p_data->update_record);
+ tBTA_JV_UPDATE_RECORD evt_data;
+ UINT32 handle;
+ INT32 i;
+ UINT8 *ptr;
+ UINT8 *next_ptr;
+ UINT8 *end;
+ UINT32 len;
+ UINT8 type;
+
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = ur->handle;
+
+ handle = bta_jv_get_sdp_handle(ur->handle);
+
+ if(handle)
+ {
+ /* this is a record created by JV */
+ for (i = 0; i < ur->array_len; i++)
+ {
+ ptr = ur->p_values[i];
+ end = ptr + ur->p_value_sizes[i];
+
+ while (ptr < end)
+ {
+ type = *ptr;
+ next_ptr = sdpu_get_len_from_type(ptr + 1, *ptr, &len);
+
+ if(ATTR_ID_SERVICE_RECORD_HDL != ur->p_ids[i])
+ {
+ if (!SDP_AddAttribute(handle, ur->p_ids[i], (UINT8)((type >> 3) & 0x1f),
+ len, next_ptr))
+ {
+ /* failed on updating attributes. */
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_UPDATE_RECORD_EVT, (tBTA_JV *)&evt_data);
+ return;
+ }
+ }
+
+ ptr = next_ptr + len;
+ } /* end of while */
+ } /* end of for */
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_UPDATE_RECORD_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_add_attribute
+**
+** Description Add an attribute to an SDP record
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_add_attribute(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_API_ADD_ATTRIBUTE *aa = &(p_data->add_attr);
+ tBTA_JV_ADD_ATTR evt_data;
+ UINT32 handle;
+ UINT8 type;
+ UINT32 len;
+ UINT8 *ptr;
+ UINT8 *next_ptr;
+
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = aa->handle;
+ handle = bta_jv_get_sdp_handle(aa->handle);
+
+ if(handle)
+ {
+ /* this is a record created by JV */
+ ptr = aa->p_value;
+ type = *ptr;
+ next_ptr = sdpu_get_len_from_type(ptr + 1, *ptr, &len);
+ APPL_TRACE_DEBUG3( "bta_jv_add_attribute: ptr chg:%d len:%d, size:%d",
+ (next_ptr - ptr), len, aa->value_size);
+ if(ATTR_ID_SERVICE_RECORD_HDL != aa->attr_id && /* do not allow the SDP record handle to be updated */
+ ((INT32)(next_ptr - ptr + len) == aa->value_size) && /* double check data size */
+ SDP_AddAttribute(handle, aa->attr_id, (UINT8)((type >> 3) & 0x1f),
+ len, next_ptr))
+ {
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+ }
+
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_ADD_ATTR_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_delete_attribute
+**
+** Description Delete an attribute from the given SDP record
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_delete_attribute(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_API_ADD_ATTRIBUTE *da = &(p_data->add_attr);
+ tBTA_JV_DELETE_ATTR evt_data;
+ UINT32 handle;
+
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = da->handle;
+ handle = bta_jv_get_sdp_handle(da->handle);
+
+ if(handle)
+ {
+ /* this is a record created by JV */
+ if(SDP_DeleteAttribute(handle, da->attr_id))
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+
+ if(bta_jv_cb.p_dm_cback)
+ bta_jv_cb.p_dm_cback(BTA_JV_DELETE_ATTR_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_delete_record
+**
+** Description Delete an SDP record
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_delete_record(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_API_ADD_ATTRIBUTE *dr = &(p_data->add_attr);
+ UINT32 handle;
+
+ handle = bta_jv_get_sdp_handle(dr->handle);
+
+ if(handle)
+ {
+ /* this is a record created by JV */
+ SDP_DeleteRecord(handle);
+ bta_jv_free_sdp_id(dr->handle);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_l2cap_client_cback
+**
+** Description handles the l2cap client events
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_l2cap_client_cback(UINT16 gap_handle, UINT16 event)
+{
+#if 0
+ tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
+ tBTA_JV evt_data;
+
+ if(gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback)
+ return;
+
+ APPL_TRACE_DEBUG2( "bta_jv_l2cap_client_cback: %d evt:x%x",
+ gap_handle, event);
+ evt_data.l2c_open.status = BTA_JV_SUCCESS;
+ evt_data.l2c_open.handle = gap_handle;
+ switch (event)
+ {
+ case GAP_EVT_CONN_OPENED:
+ bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
+ evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
+ p_cb->state = BTA_JV_ST_CL_OPEN;
+ p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data);
+ break;
+
+ case GAP_EVT_CONN_CLOSED:
+ p_cb->state = BTA_JV_ST_NONE;
+ bta_jv_free_sec_id(&p_cb->sec_id);
+ evt_data.l2c_close.async = TRUE;
+ p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data);
+ p_cb->p_cback = NULL;
+ break;
+
+ case GAP_EVT_CONN_DATA_AVAIL:
+ evt_data.handle = gap_handle;
+ p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data);
+ break;
+
+ case GAP_EVT_CONN_CONGESTED:
+ case GAP_EVT_CONN_UNCONGESTED:
+ p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
+ evt_data.l2c_cong.cong = p_cb->cong;
+ p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data);
+ break;
+
+ default:
+ break;
+ }
+#endif
+}
+
+#if SDP_FOR_JV_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function bta_jv_sdp_res_cback
+**
+** Description Callback for Start Discovery
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_sdp_res_cback (UINT16 event, tSDP_DATA *p_data)
+{
+ tBTA_JV evt_data;
+ tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[BTA_JV_L2C_FOR_SDP_HDL];
+
+ APPL_TRACE_DEBUG2( "bta_jv_sdp_res_cback: %d evt:x%x",
+ bta_jv_cb.sdp_for_jv, event);
+
+ if(!bta_jv_cb.sdp_for_jv)
+ return;
+
+ evt_data.l2c_open.status = BTA_JV_SUCCESS;
+ evt_data.l2c_open.handle = BTA_JV_L2C_FOR_SDP_HDL;
+
+ switch(event)
+ {
+ case SDP_EVT_OPEN:
+ bdcpy(evt_data.l2c_open.rem_bda, p_data->open.peer_addr);
+ evt_data.l2c_open.tx_mtu = p_data->open.peer_mtu;
+ p_cb->state = BTA_JV_ST_SR_OPEN;
+ p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data);
+ break;
+ case SDP_EVT_DATA_IND:
+ evt_data.handle = BTA_JV_L2C_FOR_SDP_HDL;
+ memcpy(p_bta_jv_cfg->p_sdp_raw_data, p_data->data.p_data, p_data->data.data_len);
+ APPL_TRACE_DEBUG2( "data size: %d/%d ", bta_jv_cb.sdp_data_size, p_data->data.data_len);
+ bta_jv_cb.sdp_data_size = p_data->data.data_len;
+ p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_sdp_cback
+**
+** Description Callback for Start Discovery
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_sdp_cback(UINT16 result)
+{
+ tBTA_JV_L2CAP_CLOSE close;
+ tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[BTA_JV_L2C_FOR_SDP_HDL];
+ APPL_TRACE_DEBUG1( "bta_jv_sdp_cback: result:x%x", result);
+
+ if(p_cb->p_cback)
+ {
+ close.handle = BTA_JV_L2C_FOR_SDP_HDL;
+ close.async = FALSE;
+ close.status = BTA_JV_SUCCESS;
+ bta_jv_free_sec_id(&p_cb->sec_id);
+ p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&close);
+ }
+
+ bta_jv_cb.sdp_for_jv = 0;
+ p_cb->p_cback = NULL;
+
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_jv_l2cap_connect
+**
+** Description makes an l2cap client connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_l2cap_connect(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_L2C_CB *p_cb;
+ tBTA_JV_L2CAP_CL_INIT evt_data;
+ UINT16 handle=GAP_INVALID_HANDLE;
+ UINT8 sec_id;
+ tL2CAP_CFG_INFO cfg;
+ tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect);
+
+ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+ cfg.mtu_present = TRUE;
+ cfg.mtu = cc->rx_mtu;
+ /* TODO: DM role manager
+ L2CA_SetDesireRole(cc->role);
+ */
+
+ sec_id = bta_jv_alloc_sec_id();
+ evt_data.sec_id = sec_id;
+ evt_data.status = BTA_JV_FAILURE;
+ if (sec_id)
+ {
+#if SDP_FOR_JV_INCLUDED == TRUE
+ if(SDP_PSM == cc->remote_psm && 0 == bta_jv_cb.sdp_for_jv)
+ {
+ bta_jv_cb.sdp_for_jv = SDP_ConnOpen(cc->peer_bd_addr,
+ bta_jv_sdp_res_cback,
+ bta_jv_sdp_cback);
+ if(bta_jv_cb.sdp_for_jv)
+ {
+ bta_jv_cb.sdp_data_size = 0;
+ handle = BTA_JV_L2C_FOR_SDP_HDL;
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+ }
+ else
+#endif
+ if(bta_jv_check_psm(cc->remote_psm)) /* allowed */
+ {
+ if( (handle = GAP_ConnOpen("", sec_id, 0, cc->peer_bd_addr, cc->remote_psm,
+ &cfg, cc->sec_mask, GAP_FCR_CHAN_OPT_BASIC,
+ bta_jv_l2cap_client_cback)) != GAP_INVALID_HANDLE )
+ {
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+ }
+ }
+
+ if (evt_data.status == BTA_JV_SUCCESS)
+ {
+ p_cb = &bta_jv_cb.l2c_cb[handle];
+ p_cb->handle = handle;
+ p_cb->p_cback = cc->p_cback;
+ p_cb->psm = 0; /* not a server */
+ p_cb->sec_id = sec_id;
+ p_cb->state = BTA_JV_ST_CL_OPENING;
+ }
+ else
+ {
+ bta_jv_free_sec_id(&sec_id);
+ }
+ evt_data.handle = handle;
+ cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_l2cap_close
+**
+** Description Close an L2CAP client connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_l2cap_close(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_L2CAP_CLOSE evt_data;
+ tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close);
+ tBTA_JV_L2CAP_CBACK *p_cback = cc->p_cb->p_cback;
+
+ evt_data.handle = cc->handle;
+ evt_data.status = bta_jv_free_l2c_cb(cc->p_cb);
+ evt_data.async = FALSE;
+
+ if (p_cback)
+ p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data);
+ else
+ APPL_TRACE_ERROR0("### NO CALLBACK SET !!! ###");
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_l2cap_server_cback
+**
+** Description handles the l2cap server callback
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_l2cap_server_cback(UINT16 gap_handle, UINT16 event)
+{
+#if 0
+ tBTA_JV_L2C_CB *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
+ tBTA_JV evt_data;
+ tBTA_JV_L2CAP_CBACK *p_cback;
+
+ if(gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback)
+ return;
+
+ APPL_TRACE_DEBUG2( "bta_jv_l2cap_server_cback: %d evt:x%x",
+ gap_handle, event);
+ evt_data.l2c_open.status = BTA_JV_SUCCESS;
+ evt_data.l2c_open.handle = gap_handle;
+
+ switch (event)
+ {
+ case GAP_EVT_CONN_OPENED:
+ bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
+ evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
+ p_cb->state = BTA_JV_ST_SR_OPEN;
+ p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data);
+ break;
+
+ case GAP_EVT_CONN_CLOSED:
+ evt_data.l2c_close.async = TRUE;
+ evt_data.l2c_close.handle = p_cb->handle;
+ p_cback = p_cb->p_cback;
+ evt_data.l2c_close.status = bta_jv_free_l2c_cb(p_cb);
+ p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data);
+ break;
+
+ case GAP_EVT_CONN_DATA_AVAIL:
+ evt_data.handle = gap_handle;
+ p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data);
+ break;
+
+ case GAP_EVT_CONN_CONGESTED:
+ case GAP_EVT_CONN_UNCONGESTED:
+ p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
+ evt_data.l2c_cong.cong = p_cb->cong;
+ p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data);
+ break;
+
+ default:
+ break;
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_l2cap_start_server
+**
+** Description starts an L2CAP server
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_L2C_CB *p_cb;
+ UINT8 sec_id;
+ UINT16 handle;
+ tL2CAP_CFG_INFO cfg;
+ tBTA_JV_L2CAP_START evt_data;
+ tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
+
+ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+
+ //FIX: MTU=0 means not present
+ if (ls->rx_mtu >0)
+ {
+ cfg.mtu_present = TRUE;
+ cfg.mtu = ls->rx_mtu;
+ }
+ else
+ {
+ cfg.mtu_present = FALSE;
+ cfg.mtu = 0;
+ }
+
+ /* TODO DM role manager
+ L2CA_SetDesireRole(ls->role);
+ */
+
+ sec_id = bta_jv_alloc_sec_id();
+ if (0 == sec_id || (FALSE == bta_jv_check_psm(ls->local_psm)) ||
+ (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, 0, ls->local_psm, &cfg,
+ ls->sec_mask, GAP_FCR_CHAN_OPT_BASIC, bta_jv_l2cap_server_cback)) == GAP_INVALID_HANDLE)
+ {
+ bta_jv_free_sec_id(&sec_id);
+ evt_data.status = BTA_JV_FAILURE;
+ }
+ else
+ {
+ /* default JV implementation requires explicit call
+ to allow incoming connections when ready*/
+
+ GAP_SetAcceptReady(handle, FALSE);
+
+ p_cb = &bta_jv_cb.l2c_cb[handle];
+ evt_data.status = BTA_JV_SUCCESS;
+ evt_data.handle = handle;
+ evt_data.sec_id = sec_id;
+ p_cb->p_cback = ls->p_cback;
+ p_cb->handle = handle;
+ p_cb->sec_id = sec_id;
+ p_cb->state = BTA_JV_ST_SR_LISTEN;
+ p_cb->psm = ls->local_psm;
+ }
+ ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_l2cap_stop_server
+**
+** Description stops an L2CAP server
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_L2C_CB *p_cb;
+ tBTA_JV_L2CAP_CLOSE evt_data;
+ tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
+ tBTA_JV_L2CAP_CBACK *p_cback;
+ int i;
+
+ for(i=0; i<BTA_JV_MAX_L2C_CONN; i++)
+ {
+ if(bta_jv_cb.l2c_cb[i].psm == ls->local_psm)
+ {
+ p_cb = &bta_jv_cb.l2c_cb[i];
+ p_cback = p_cb->p_cback;
+ evt_data.handle = p_cb->handle;
+ evt_data.status = bta_jv_free_l2c_cb(p_cb);
+ evt_data.async = FALSE;
+ p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data);
+ break;
+ }
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_l2cap_read
+**
+** Description Read data from an L2CAP connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_l2cap_read(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_L2CAP_READ evt_data;
+ tBTA_JV_API_L2CAP_READ *rc = &(p_data->l2cap_read);
+
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = rc->handle;
+ evt_data.req_id = rc->req_id;
+ evt_data.p_data = rc->p_data;
+ evt_data.len = 0;
+#if SDP_FOR_JV_INCLUDED == TRUE
+ if(BTA_JV_L2C_FOR_SDP_HDL == rc->handle)
+ {
+ evt_data.len = rc->len;
+ if(evt_data.len > bta_jv_cb.sdp_data_size)
+ evt_data.len = bta_jv_cb.sdp_data_size;
+
+ memcpy(rc->p_data, p_bta_jv_cfg->p_sdp_raw_data, evt_data.len);
+ bta_jv_cb.sdp_data_size = 0;
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+ else
+#endif
+ if (BT_PASS == GAP_ConnReadData(rc->handle, rc->p_data, rc->len, &evt_data.len))
+ {
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+
+ rc->p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function bta_jv_l2cap_write
+**
+** Description Write data to an L2CAP connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_l2cap_write(tBTA_JV_MSG *p_data)
+{
+#if 0
+ tBTA_JV_L2CAP_WRITE evt_data;
+ tBTA_JV_API_L2CAP_WRITE *ls = &(p_data->l2cap_write);
+
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = ls->handle;
+ evt_data.req_id = ls->req_id;
+ evt_data.cong = ls->p_cb->cong;
+ evt_data.len = 0;
+#if SDP_FOR_JV_INCLUDED == TRUE
+ if(BTA_JV_L2C_FOR_SDP_HDL == ls->handle)
+ {
+ UINT8 *p;
+ BT_HDR *p_msg = (BT_HDR *) GKI_getbuf ((UINT16)(ls->len + BT_HDR_SIZE + L2CAP_MIN_OFFSET));
+ if(p_msg)
+ {
+ p_msg->offset = L2CAP_MIN_OFFSET;
+ p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
+ p_msg->len = ls->len;
+ memcpy(p, ls->p_data, p_msg->len);
+ if(SDP_WriteData (bta_jv_cb.sdp_for_jv, p_msg))
+ {
+ evt_data.len = ls->len;
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+ }
+ }
+ else
+#endif
+ if (!evt_data.cong &&
+ BT_PASS == GAP_ConnWriteData(ls->handle, ls->p_data, ls->len, &evt_data.len))
+ {
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+
+ ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_port_data_co_cback
+**
+** Description port data callback function of rfcomm
+** connections
+**
+** Returns void
+**
+*******************************************************************************/
+/*
+#define DATA_CO_CALLBACK_TYPE_INCOMING 1
+#define DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE 2
+#define DATA_CO_CALLBACK_TYPE_OUTGOING 3
+*/
+static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len, int type)
+{
+ tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+ tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+
+ if (p_cb != NULL)
+ {
+ switch(type)
+ {
+ case DATA_CO_CALLBACK_TYPE_INCOMING:
+ return bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR*)buf);
+ case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE:
+ return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int*)buf);
+ case DATA_CO_CALLBACK_TYPE_OUTGOING:
+ return bta_co_rfc_data_outgoing(p_pcb->user_data, buf, len);
+ default:
+ APPL_TRACE_ERROR1("unknown callout type:%d", type);
+ break;
+ }
+ }
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_port_mgmt_cl_cback
+**
+** Description callback for port mamangement function of rfcomm
+** client connections
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle)
+{
+ tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+ tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+ tBTA_JV evt_data;
+ BD_ADDR rem_bda;
+ UINT16 lcid;
+ tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */
+
+ APPL_TRACE_DEBUG1( "bta_jv_port_mgmt_cl_cback:%d", port_handle);
+ if(NULL == p_cb || NULL == p_cb->p_cback)
+ return;
+
+ APPL_TRACE_DEBUG3( "bta_jv_port_mgmt_cl_cback code=%d port_handle:%d handle:%d",
+ code, port_handle, p_cb->handle);
+
+ PORT_CheckConnection(port_handle, rem_bda, &lcid);
+
+ if(code == PORT_SUCCESS)
+ {
+ evt_data.rfc_open.handle = p_cb->handle;
+ evt_data.rfc_open.status = BTA_JV_SUCCESS;
+ bdcpy(evt_data.rfc_open.rem_bda, rem_bda);
+ p_pcb->state = BTA_JV_ST_CL_OPEN;
+ p_cb->p_cback(BTA_JV_RFCOMM_OPEN_EVT, &evt_data, p_pcb->user_data);
+ }
+ else
+ {
+ evt_data.rfc_close.handle = p_cb->handle;
+ evt_data.rfc_close.status = BTA_JV_FAILURE;
+ evt_data.rfc_close.port_status = code;
+ evt_data.rfc_close.async = TRUE;
+ if (p_pcb->state == BTA_JV_ST_CL_CLOSING)
+ {
+ evt_data.rfc_close.async = FALSE;
+ }
+ p_pcb->state = BTA_JV_ST_NONE;
+ p_pcb->cong = FALSE;
+ p_cback = p_cb->p_cback;
+ bta_jv_free_rfc_cb(p_cb);
+
+ p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, p_pcb->user_data);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_port_event_cl_cback
+**
+** Description Callback for RFCOMM client port events
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle)
+{
+ tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+ tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+ tBTA_JV evt_data;
+
+ APPL_TRACE_DEBUG1( "bta_jv_port_event_cl_cback:%d", port_handle);
+ if(NULL == p_cb || NULL == p_cb->p_cback)
+ return;
+
+ APPL_TRACE_DEBUG3( "bta_jv_port_event_cl_cback code=x%x port_handle:%d handle:%d",
+ code, port_handle, p_cb->handle);
+ if (code & PORT_EV_RXCHAR)
+ {
+ evt_data.data_ind.handle = p_cb->handle;
+ p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, p_pcb->user_data);
+ }
+
+ if (code & PORT_EV_FC)
+ {
+ p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
+ evt_data.rfc_cong.cong = p_pcb->cong;
+ evt_data.rfc_cong.handle = p_cb->handle;
+ evt_data.rfc_cong.status = BTA_JV_SUCCESS;
+ p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, p_pcb->user_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_rfcomm_connect
+**
+** Description Client initiates an RFCOMM connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_connect(tBTA_JV_MSG *p_data)
+{
+ UINT16 handle = 0;
+ UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS);
+ tPORT_STATE port_state;
+ UINT8 sec_id;
+ tBTA_JV_RFC_CB *p_cb = NULL;
+ tBTA_JV_PCB *p_pcb;
+ tBTA_JV_API_RFCOMM_CONNECT *cc = &(p_data->rfcomm_connect);
+ tBTA_JV_RFCOMM_CL_INIT evt_data;
+
+ /* TODO DM role manager
+ L2CA_SetDesireRole(cc->role);
+ */
+
+ sec_id = bta_jv_alloc_sec_id();
+ evt_data.sec_id = sec_id;
+ evt_data.status = BTA_JV_SUCCESS;
+ if (0 == sec_id ||
+ BTM_SetSecurityLevel(TRUE, "", sec_id, cc->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, cc->remote_scn) == FALSE)
+ {
+ evt_data.status = BTA_JV_FAILURE;
+ error("sec_id:%d is zero or BTM_SetSecurityLevel failed, remote_scn:%d", sec_id, cc->remote_scn);
+ }
+
+ if (evt_data.status == BTA_JV_SUCCESS &&
+ RFCOMM_CreateConnection(UUID_SERVCLASS_SERIAL_PORT, cc->remote_scn, FALSE,
+ BTA_JV_DEF_RFC_MTU, cc->peer_bd_addr, &handle, bta_jv_port_mgmt_cl_cback) != PORT_SUCCESS)
+ {
+ evt_data.status = BTA_JV_FAILURE;
+ }
+ if (evt_data.status == BTA_JV_SUCCESS)
+ {
+ p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
+ if(p_cb)
+ {
+ p_cb->p_cback = cc->p_cback;
+ p_cb->sec_id = sec_id;
+ p_cb->scn = 0;
+ p_pcb->state = BTA_JV_ST_CL_OPENING;
+ p_pcb->user_data = cc->user_data;
+ evt_data.use_co = TRUE;
+
+ PORT_SetEventCallback(handle, bta_jv_port_event_cl_cback);
+ PORT_SetEventMask(handle, event_mask);
+ PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
+
+ PORT_GetState(handle, &port_state);
+
+ port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
+
+ /* coverity[uninit_use_in_call]
+ FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
+ PORT_SetState(handle, &port_state);
+
+ evt_data.handle = p_cb->handle;
+ }
+ else
+ {
+ evt_data.status = BTA_JV_FAILURE;
+ APPL_TRACE_ERROR0("run out of rfc control block");
+ }
+ }
+ cc->p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
+ }
+
+/*******************************************************************************
+**
+** Function bta_jv_rfcomm_close
+**
+** Description Close an RFCOMM connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_RFCOMM_CLOSE evt_data;
+ tBTA_JV_API_RFCOMM_CLOSE *cc = &(p_data->rfcomm_close);
+ tBTA_JV_RFC_CB *p_cb = cc->p_cb;
+ tBTA_JV_PCB *p_pcb = cc->p_pcb;
+ tBTA_JV_RFCOMM_CBACK *p_cback = p_cb->p_cback;
+
+ evt_data.handle = p_cb->handle;
+ evt_data.status = BTA_JV_FAILURE;
+
+ void* user_data = p_pcb->user_data;
+ p_pcb->cong = FALSE;
+ if(p_pcb->state <= BTA_JV_ST_CL_MAX)
+ {
+ if(p_pcb->state == BTA_JV_ST_CL_OPEN)
+ {
+ if(PORT_SUCCESS == RFCOMM_RemoveConnection(p_pcb->port_handle))
+ {
+ p_pcb->state = BTA_JV_ST_CL_CLOSING;
+ return;
+ }
+ }
+ evt_data.status = bta_jv_free_rfc_cb(p_cb);
+ }
+ else if(BTA_JV_ST_SR_OPEN == p_pcb->state)
+ {
+ /* server is connected */
+ if(PORT_SUCCESS == RFCOMM_RemoveConnection(p_pcb->port_handle))
+ {
+ p_pcb->state = BTA_JV_ST_SR_CLOSING;
+ return;
+ }
+ }
+
+ evt_data.async = FALSE;
+
+ if (p_cback)
+ p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
+ else
+ error("### NO CALLBACK SET !!! ###");
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_get_num_rfc_listen
+**
+** Description when a RFCOMM connection goes down, make sure that there's only
+** one port stays listening on this scn.
+**
+** Returns
+**
+*******************************************************************************/
+static UINT8 bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB *p_cb)
+{
+ UINT8 i, listen=1;
+ tBTA_JV_PCB *p_pcb;
+
+ if (p_cb->max_sess > 1)
+ {
+ listen = 0;
+ for (i=0; i<p_cb->max_sess; i++)
+ {
+ if (p_cb->rfc_hdl[i] != 0)
+ {
+ p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
+ if (BTA_JV_ST_SR_LISTEN == p_pcb->state)
+ {
+ listen++;
+ }
+ }
+ }
+ }
+ return listen;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_port_mgmt_sr_cback
+**
+** Description callback for port mamangement function of rfcomm
+** server connections
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle)
+{
+ tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+ tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+ tBTA_JV evt_data;
+ BD_ADDR rem_bda;
+ UINT16 lcid;
+ UINT8 num;
+ tBTA_JV_RFCOMM_CBACK *p_cback;
+ UINT32 si;
+
+ if(NULL == p_cb || NULL == p_cb->p_cback)
+ return;
+ void *user_data = p_pcb->user_data;
+ APPL_TRACE_DEBUG4( "bta_jv_port_mgmt_sr_cback code=%d port_handle:%d handle:%d/0x%x",
+ code, port_handle, p_cb->handle, p_pcb->handle);
+
+ PORT_CheckConnection(port_handle, rem_bda, &lcid);
+ int failed = TRUE;
+ if(code == PORT_SUCCESS)
+ {
+ evt_data.rfc_srv_open.handle = p_pcb->handle;
+ evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
+ bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda);
+ p_pcb->state = BTA_JV_ST_SR_OPEN;
+ tBTA_JV_PCB *p_pcb_new_listen = bta_jv_add_rfc_port(p_cb);
+ if(p_pcb_new_listen)
+ {
+ evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle;
+ p_pcb_new_listen->user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
+ failed = FALSE;
+ }
+ else error("bta_jv_add_rfc_port failed to create new listen port");
+ }
+ if(failed)
+ {
+ evt_data.rfc_close.handle = p_cb->handle;
+ evt_data.rfc_close.status = BTA_JV_SUCCESS;
+ evt_data.rfc_close.async = TRUE;
+ if(BTA_JV_ST_SR_CLOSING == p_pcb->state)
+ {
+ evt_data.rfc_close.async = FALSE;
+ }
+ p_pcb->cong = FALSE;
+ p_cback = p_cb->p_cback;
+ APPL_TRACE_DEBUG1( "removing rfc handle:0x%x", p_pcb->handle);
+ si = BTA_JV_RFC_HDL_TO_SIDX(p_pcb->handle);
+ p_cb->rfc_hdl[si] = 0;
+ p_pcb->state = BTA_JV_ST_NONE;
+ p_pcb->handle = 0;
+ RFCOMM_RemoveServer(port_handle);
+ evt_data.rfc_close.port_status = code;
+ p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_port_event_sr_cback
+**
+** Description Callback for RFCOMM server port events
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle)
+{
+ tBTA_JV_PCB *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+ tBTA_JV_RFC_CB *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+ tBTA_JV evt_data;
+
+ if(NULL == p_cb || NULL == p_cb->p_cback)
+ return;
+
+ APPL_TRACE_DEBUG3( "bta_jv_port_event_sr_cback code=x%x port_handle:%d handle:%d",
+ code, port_handle, p_cb->handle);
+
+ void *user_data = p_pcb->user_data;
+ if (code & PORT_EV_RXCHAR)
+ {
+ evt_data.data_ind.handle = p_cb->handle;
+ p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, user_data);
+ }
+
+ if (code & PORT_EV_FC)
+ {
+ p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
+ evt_data.rfc_cong.cong = p_pcb->cong;
+ evt_data.rfc_cong.handle = p_cb->handle;
+ evt_data.rfc_cong.status = BTA_JV_SUCCESS;
+ p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, user_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_add_rfc_port
+**
+** Description add a port for server when the existing posts is open
+**
+** Returns return a pointer to tBTA_JV_PCB just added
+**
+*******************************************************************************/
+static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb)
+{
+ UINT8 used = 0, i, listen=0;
+ UINT32 si = 0;
+ tBTA_JV_PCB *p_pcb = NULL;
+ tPORT_STATE port_state;
+ UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS);
+
+ if (p_cb->max_sess > 1)
+ {
+ for (i=0; i<p_cb->max_sess; i++)
+ {
+ if (p_cb->rfc_hdl[i] != 0)
+ {
+ p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
+ if (p_pcb->state == BTA_JV_ST_SR_LISTEN)
+ listen++;
+ used++;
+ }
+ else if (si==0)
+ {
+ si = (UINT32)(i + 1);
+ }
+ }
+
+ debug("bta_jv_add_rfc_port max_sess=%d used:%d listen:%d si:%d",
+ p_cb->max_sess, used, listen, si);
+ if (used <p_cb->max_sess && listen==0 && si)
+ {
+ si--;
+ if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE,
+ BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS)
+ {
+ p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1];
+ p_pcb->state = BTA_JV_ST_SR_LISTEN;
+ p_pcb->port_handle = p_cb->rfc_hdl[si];
+ PORT_SetEventCallback(p_pcb->port_handle, bta_jv_port_event_sr_cback);
+ PORT_SetDataCOCallback (p_pcb->port_handle, bta_jv_port_data_co_cback);
+ PORT_SetEventMask(p_pcb->port_handle, event_mask);
+ PORT_GetState(p_pcb->port_handle, &port_state);
+
+ port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
+
+/* coverity[uninit_use_in_call]
+FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
+ PORT_SetState(p_pcb->port_handle, &port_state);
+ p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si);
+ APPL_TRACE_DEBUG1( "new rfc handle:0x%x", p_pcb->handle);
+ }
+ }
+ }
+ return p_pcb;
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_rfcomm_start_server
+**
+** Description waits for an RFCOMM client to connect
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data)
+{
+ UINT16 handle = 0;
+ UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS);
+ tPORT_STATE port_state;
+ UINT8 sec_id;
+ tBTA_JV_RFC_CB *p_cb = NULL;
+ tBTA_JV_PCB *p_pcb;
+ tBTA_JV_API_RFCOMM_SERVER *rs = &(p_data->rfcomm_server);
+ tBTA_JV_RFCOMM_START evt_data;
+
+ /* TODO DM role manager
+ L2CA_SetDesireRole(rs->role);
+ */
+ evt_data.status = BTA_JV_FAILURE;
+ do
+ {
+ sec_id = bta_jv_alloc_sec_id();
+
+ if (0 == sec_id ||
+ BTM_SetSecurityLevel(FALSE, "JV PORT", sec_id, rs->sec_mask,
+ BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, rs->local_scn) == FALSE)
+ {
+ break;
+ }
+
+ if (RFCOMM_CreateConnection(sec_id, rs->local_scn, TRUE,
+ BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &handle, bta_jv_port_mgmt_sr_cback) != PORT_SUCCESS)
+ {
+ break;
+ }
+
+ p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
+ if(!p_cb)
+ {
+ APPL_TRACE_ERROR0("run out of rfc control block");
+ break;
+ }
+
+ p_cb->max_sess = rs->max_session;
+ p_cb->p_cback = rs->p_cback;
+ p_cb->sec_id = sec_id;
+ p_cb->scn = rs->local_scn;
+ p_pcb->state = BTA_JV_ST_SR_LISTEN;
+ p_pcb->user_data = rs->user_data;
+ evt_data.status = BTA_JV_SUCCESS;
+ evt_data.handle = p_cb->handle;
+ evt_data.sec_id = sec_id;
+ evt_data.use_co = TRUE; //FALSE;
+
+ PORT_SetEventCallback(handle, bta_jv_port_event_sr_cback);
+ PORT_SetEventMask(handle, event_mask);
+ PORT_GetState(handle, &port_state);
+
+ port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
+
+/* coverity[uninit_use_in_call]
+FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
+ PORT_SetState(handle, &port_state);
+ } while (0);
+
+ rs->p_cback(BTA_JV_RFCOMM_START_EVT, (tBTA_JV *)&evt_data, rs->user_data);
+ if(evt_data.status == BTA_JV_SUCCESS)
+ {
+ PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_rfcomm_stop_server
+**
+** Description stops an RFCOMM server
+**
+** Returns void
+**
+*******************************************************************************/
+
+void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_RFCOMM_CLOSE evt_data;
+ int i;
+ tBTA_JV_API_RFCOMM_SERVER *ls = &(p_data->rfcomm_server);
+ HDL2CB(ls->rfc_handle);
+ evt_data.status = BTA_JV_FAILURE;
+ if(p_cb && p_pcb)
+ {
+ evt_data.handle = p_cb->handle;
+ void* user_data = p_pcb->user_data;
+ evt_data.status = bta_jv_free_rfc_listen_cb(p_cb);
+ evt_data.async = FALSE;
+
+ /* occasionally when shutting down stack the callback is already
+ freed, hence make sure we check for this condition (pending investigatation
+ of rootcause) */
+ debug("send BTA_JV_RFCOMM_CLOSE_EVT");
+ if( p_cb->p_cback)
+ p_cb->p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
+ }
+ else
+ {
+ debug("warning, no jv callback set");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_rfcomm_read
+**
+** Description Read data from an RFCOMM connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_read(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_API_RFCOMM_READ *rc = &(p_data->rfcomm_read);
+ tBTA_JV_RFC_CB *p_cb = rc->p_cb;
+ tBTA_JV_PCB *p_pcb = rc->p_pcb;
+ tBTA_JV_RFCOMM_READ evt_data;
+
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = p_cb->handle;
+ evt_data.req_id = rc->req_id;
+ evt_data.p_data = rc->p_data;
+ if (PORT_ReadData(rc->p_pcb->port_handle, (char *)rc->p_data, rc->len, &evt_data.len) ==
+ PORT_SUCCESS)
+ {
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+
+ p_cb->p_cback(BTA_JV_RFCOMM_READ_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_jv_rfcomm_write
+**
+** Description write data to an RFCOMM connection
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data)
+{
+ tBTA_JV_API_RFCOMM_WRITE *wc = &(p_data->rfcomm_write);
+ tBTA_JV_RFC_CB *p_cb = wc->p_cb;
+ tBTA_JV_PCB *p_pcb = wc->p_pcb;
+ tBTA_JV_RFCOMM_WRITE evt_data;
+
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = p_cb->handle;
+ evt_data.req_id = wc->req_id;
+ evt_data.cong = p_pcb->cong;
+ evt_data.len = 0;
+ if (!evt_data.cong &&
+ PORT_WriteDataCO(p_pcb->port_handle, &evt_data.len) ==
+ PORT_SUCCESS)
+ {
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+ //update congestion flag
+ evt_data.cong = p_pcb->cong;
+ if (p_cb->p_cback)
+ {
+ p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_jv_rfcomm_write :: WARNING ! No JV callback set");
+ }
+}
+
diff --git a/bta/jv/bta_jv_api.c b/bta/jv/bta_jv_api.c
new file mode 100644
index 0000000..8953886
--- /dev/null
+++ b/bta/jv/bta_jv_api.c
@@ -0,0 +1,1584 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation of the JAVA API for Bluetooth Wireless
+ * Technology (JABWT) as specified by the JSR82 specificiation
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_jv_api.h"
+#include "bta_jv_int.h"
+#include "gki.h"
+#include <string.h>
+#include "port_api.h"
+#include "sdp_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_jv_reg =
+{
+ bta_jv_sm_execute,
+ NULL
+};
+
+/*******************************************************************************
+**
+** Function BTA_JvEnable
+**
+** Description Enable the Java I/F service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_JV_ENABLE_EVT. This function must
+** be called before other function in the JV API are
+** called.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_ENABLE *p_buf;
+
+ APPL_TRACE_API0( "BTA_JvEnable");
+ if(p_cback && FALSE == bta_sys_is_register(BTA_ID_JV))
+ {
+ memset(&bta_jv_cb, 0, sizeof(tBTA_JV_CB));
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_JV, &bta_jv_reg);
+ GKI_sched_unlock();
+
+ if (p_cback && (p_buf = (tBTA_JV_API_ENABLE *) GKI_getbuf(sizeof(tBTA_JV_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_JV_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ bta_sys_sendmsg(p_buf);
+ status = BTA_JV_SUCCESS;
+ }
+ }
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvDisable
+**
+** Description Disable the Java I/F
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_JvDisable(void)
+{
+ BT_HDR *p_buf;
+
+ APPL_TRACE_API0( "BTA_JvDisable");
+ bta_sys_deregister(BTA_ID_JV);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_JV_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvIsEnable
+**
+** Description Get the JV registration status.
+**
+** Returns TRUE, if registered
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsEnable(void)
+{
+ return bta_sys_is_register(BTA_ID_JV);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvSetDiscoverability
+**
+** Description This function sets the Bluetooth discoverable modes
+** of the local device. This controls whether other
+** Bluetooth devices can find the local device.
+**
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_SET_DISCOVER_EVT.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvSetDiscoverability(tBTA_JV_DISC disc_mode)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_SET_DISCOVERABILITY *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvSetDiscoverability");
+ if ((p_msg = (tBTA_JV_API_SET_DISCOVERABILITY *)GKI_getbuf(sizeof(tBTA_JV_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_SET_DISCOVERABILITY_EVT;
+ p_msg->disc_mode = disc_mode;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetDiscoverability
+**
+** Description This function gets the Bluetooth
+** discoverable modes of local device
+**
+** Returns The current Bluetooth discoverable mode.
+**
+*******************************************************************************/
+tBTA_JV_DISC BTA_JvGetDiscoverability(void)
+{
+ APPL_TRACE_API0( "BTA_JvGetDiscoverability");
+ return BTM_ReadDiscoverability(0, 0);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetLocalDeviceAddr
+**
+** Description This function obtains the local Bluetooth device address.
+** The local Bluetooth device address is reported by the
+** tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_ADDR_EVT.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetLocalDeviceAddr(void)
+{
+ tBTA_JV_STATUS ret = BTA_JV_FAILURE;
+ BT_HDR *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvGetLocalDeviceAddr");
+ if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT;
+ bta_sys_sendmsg(p_msg);
+ ret = BTA_JV_SUCCESS;
+ }
+
+ return(ret);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetLocalDeviceName
+**
+** Description This function obtains the name of the local device
+** The local Bluetooth device name is reported by the
+** tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_NAME_EVT.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetLocalDeviceName(void)
+{
+ tBTA_JV_STATUS ret = BTA_JV_FAILURE;
+ BT_HDR *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvGetLocalDeviceName");
+ if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT;
+ bta_sys_sendmsg(p_msg);
+ ret = BTA_JV_SUCCESS;
+ }
+
+ return(ret);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetRemoteDeviceName
+**
+** Description This function obtains the name of the specified device.
+** The Bluetooth device name is reported by the
+** tBTA_JV_DM_CBACK callback with a BTA_JV_REMOTE_NAME_EVT.
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetRemoteDeviceName(BD_ADDR bd_addr)
+{
+ tBTA_JV_STATUS ret = BTA_JV_FAILURE;
+ tBTA_JV_API_GET_REMOTE_NAME *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvGetRemoteDeviceName");
+ if ((p_msg = (tBTA_JV_API_GET_REMOTE_NAME *)GKI_getbuf(sizeof(tBTA_JV_API_GET_REMOTE_NAME))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_msg);
+ ret = BTA_JV_SUCCESS;
+ }
+
+ return(ret);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetPreknownDevice
+**
+** Description This function obtains the Bluetooth address in the inquiry
+** database collected via the previous call to BTA_DmSearch().
+**
+** Returns The number of preknown devices if p_bd_addr is NULL
+** BTA_JV_SUCCESS if successful.
+** BTA_JV_INTERNAL_ERR(-1) if internal failure.
+**
+*******************************************************************************/
+INT32 BTA_JvGetPreknownDevice(UINT8 * p_bd_addr, UINT32 index)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTM_INQ_INFO *p_info;
+ UINT32 count = 0;
+ INT32 ret = BTA_JV_INTERNAL_ERR;
+
+ APPL_TRACE_API0( "BTA_JvGetPreknownDevice");
+ p_info = BTM_InqFirstResult();
+ if(p_info)
+ {
+ status = BTA_JV_SUCCESS;
+ /* the database is valid */
+ if(NULL == p_bd_addr)
+ {
+ /* p_bd_addr is NULL: count the number of preknown devices */
+ /* set the index to an invalid size (too big) */
+ index = BTM_INQ_DB_SIZE;
+ }
+ else if(index >= BTM_INQ_DB_SIZE)
+ {
+ /* invalid index - error */
+ status = (tBTA_JV_STATUS)BTA_JV_INTERNAL_ERR;
+ }
+
+ if(BTA_JV_SUCCESS == status)
+ {
+ while(p_info && index > count)
+ {
+ count++;
+ p_info = BTM_InqNextResult(p_info);
+ }
+
+ if(p_bd_addr)
+ {
+ if(index == count && p_info)
+ {
+ count = BTA_JV_SUCCESS;
+ bdcpy(p_bd_addr, p_info->results.remote_bd_addr);
+ }
+ else
+ status = (tBTA_JV_STATUS)BTA_JV_INTERNAL_ERR;
+ }
+ /*
+ else report the count
+ */
+ }
+ /*
+ else error had happened.
+ */
+ }
+
+ if(BTA_JV_SUCCESS == status)
+ {
+ ret = count;
+ }
+ return ret;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_JvGetDeviceClass
+**
+** Description This function obtains the local Class of Device. This
+** function executes in place. The result is returned right away.
+**
+** Returns DEV_CLASS, A three-byte array of UINT8 that contains the
+** Class of Device information. The definitions are in the
+** "Bluetooth Assigned Numbers".
+**
+*******************************************************************************/
+UINT8 * BTA_JvGetDeviceClass(void)
+{
+ APPL_TRACE_API0( "BTA_JvGetDeviceClass");
+ return BTM_ReadDeviceClass();
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvSetServiceClass
+**
+** Description This function sets the service class of local Class of Device
+**
+** Returns BTA_JV_SUCCESS if successful.
+** BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvSetServiceClass(UINT32 service)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_SET_SERVICE_CLASS *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvSetServiceClass");
+ if ((p_msg = (tBTA_JV_API_SET_SERVICE_CLASS *)GKI_getbuf(sizeof(tBTA_JV_API_SET_SERVICE_CLASS))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_SET_SERVICE_CLASS_EVT;
+ p_msg->service = service;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvSetEncryption
+**
+** Description This function ensures that the connection to the given device
+** is encrypted.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_SET_ENCRYPTION_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvSetEncryption(BD_ADDR bd_addr)
+{
+ tBTA_JV_STATUS ret = BTA_JV_FAILURE;
+ tBTA_JV_API_SET_ENCRYPTION *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvSetEncryption");
+ if ((p_msg = (tBTA_JV_API_SET_ENCRYPTION *)GKI_getbuf(sizeof(tBTA_JV_API_SET_ENCRYPTION))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_SET_ENCRYPTION_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_msg);
+ ret = BTA_JV_SUCCESS;
+ }
+
+ return(ret);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvIsAuthenticated
+**
+** Description This function checks if the peer device is authenticated
+**
+** Returns TRUE if authenticated.
+** FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsAuthenticated(BD_ADDR bd_addr)
+{
+ BOOLEAN is_authenticated = FALSE;
+ UINT8 sec_flags;
+
+ if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+ {
+ if(sec_flags&BTM_SEC_FLAG_AUTHENTICATED)
+ is_authenticated = TRUE;
+ }
+ return is_authenticated;
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvIsTrusted
+**
+** Description This function checks if the peer device is trusted
+** (previously paired)
+**
+** Returns TRUE if trusted.
+** FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsTrusted(BD_ADDR bd_addr)
+{
+ BOOLEAN is_trusted = FALSE;
+ UINT8 sec_flags;
+
+ if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+ {
+ if ((sec_flags&BTM_SEC_FLAG_AUTHENTICATED) ||
+ (sec_flags&BTM_SEC_FLAG_LKEY_KNOWN))
+ {
+ is_trusted = TRUE;
+ }
+ }
+ return is_trusted;
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvIsAuthorized
+**
+** Description This function checks if the peer device is authorized
+**
+** Returns TRUE if authorized.
+** FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsAuthorized(BD_ADDR bd_addr)
+{
+ BOOLEAN is_authorized = FALSE;
+ UINT8 sec_flags;
+
+ if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+ {
+ if(sec_flags&BTM_SEC_FLAG_AUTHORIZED)
+ is_authorized = TRUE;
+ }
+ return is_authorized;
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvIsEncrypted
+**
+** Description This function checks if the link to peer device is encrypted
+**
+** Returns TRUE if encrypted.
+** FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsEncrypted(BD_ADDR bd_addr)
+{
+ BOOLEAN is_encrypted = FALSE;
+ UINT8 sec_flags;
+
+ if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+ {
+ if(sec_flags&BTM_SEC_FLAG_ENCRYPTED)
+ is_encrypted = TRUE;
+ }
+ return is_encrypted;
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetSecurityMode
+**
+** Description This function returns the current Bluetooth security mode
+** of the local device
+**
+** Returns The current Bluetooth security mode.
+**
+*******************************************************************************/
+tBTA_JV_SEC_MODE BTA_JvGetSecurityMode(void)
+{
+ return BTM_GetSecurityMode();
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetSCN
+**
+** Description This function reserves a SCN (server channel number) for
+** applications running over RFCOMM. It is primarily called by
+** server profiles/applications to register their SCN into the
+** SDP database. The SCN is reported by the tBTA_JV_DM_CBACK
+** callback with a BTA_JV_GET_SCN_EVT.
+** If the SCN reported is 0, that means all SCN resources are
+** exhausted.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetSCN(void)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ BT_HDR *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvGetSCN");
+ if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = BTA_JV_API_GET_SCN_EVT;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvFreeSCN
+**
+** Description This function frees a server channel number that was used
+** by an application running over RFCOMM.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvFreeSCN(UINT8 scn)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_FREE_SCN *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvFreeSCN");
+ if ((p_msg = (tBTA_JV_API_FREE_SCN *)GKI_getbuf(sizeof(tBTA_JV_API_FREE_SCN))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_FREE_SCN_EVT;
+ p_msg->scn = scn;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetPSM
+**
+** Description This function reserves a PSM (Protocol Service Multiplexer)
+** applications running over L2CAP. It is primarily called by
+** server profiles/applications to register their PSM into the
+** SDP database.
+**
+** Returns The next free PSM
+**
+*******************************************************************************/
+UINT16 BTA_JvGetPSM(void)
+{
+#if 0
+ APPL_TRACE_API0( "BTA_JvGetPSM");
+
+ return (L2CA_AllocatePSM());
+#endif
+ return 0;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_JvStartDiscovery
+**
+** Description This function performs service discovery for the services
+** provided by the given peer device. When the operation is
+** complete the tBTA_JV_DM_CBACK callback function will be
+** called with a BTA_JV_DISCOVERY_COMP_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid,
+ tSDP_UUID *p_uuid_list, void * user_data)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_START_DISCOVERY *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvStartDiscovery");
+ if ((p_msg = (tBTA_JV_API_START_DISCOVERY *)GKI_getbuf(sizeof(tBTA_JV_API_START_DISCOVERY))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_START_DISCOVERY_EVT;
+ bdcpy(p_msg->bd_addr, bd_addr);
+ p_msg->num_uuid = num_uuid;
+ memcpy(p_msg->uuid_list, p_uuid_list, num_uuid * sizeof(tSDP_UUID));
+ p_msg->num_attr = 0;
+ p_msg->user_data = user_data;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvCancelDiscovery
+**
+** Description This function cancels an active service discovery.
+** When the operation is
+** complete the tBTA_JV_DM_CBACK callback function will be
+** called with a BTA_JV_CANCEL_DISCVRY_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvCancelDiscovery(void * user_data)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_CANCEL_DISCOVERY *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvCancelDiscovery");
+ if ((p_msg = (tBTA_JV_API_CANCEL_DISCOVERY *)GKI_getbuf(sizeof(tBTA_JV_API_CANCEL_DISCOVERY))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_CANCEL_DISCOVERY_EVT;
+ p_msg->user_data = user_data;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvGetServicesLength
+**
+** Description This function obtains the number of services and the length
+** of each service found in the SDP database (result of last
+** BTA_JvStartDiscovery().When the operation is complete the
+** tBTA_JV_DM_CBACK callback function will be called with a
+** BTA_JV_SERVICES_LEN_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetServicesLength(BOOLEAN inc_hdr, UINT16 *p_services_len)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_GET_SERVICES_LENGTH *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvGetServicesLength");
+ if ((p_msg = (tBTA_JV_API_GET_SERVICES_LENGTH *)GKI_getbuf(sizeof(tBTA_JV_API_GET_SERVICES_LENGTH))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_GET_SERVICES_LENGTH_EVT;
+ p_msg->p_services_len = p_services_len;
+ p_msg->inc_hdr = inc_hdr;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+/*******************************************************************************
+**
+** Function BTA_JvGetServicesResult
+**
+** Description This function returns a number of service records found
+** during current service search, equals to the number returned
+** by previous call to BTA_JvGetServicesLength.
+** The contents of each SDP record will be returned under a
+** TLV (type, len, value) representation in the data buffer
+** provided by the caller.
+**
+** Returns -1, if error. Otherwise, the number of services
+**
+*******************************************************************************/
+INT32 BTA_JvGetServicesResult(BOOLEAN inc_hdr, UINT8 **TLVs)
+{
+#if 0
+ INT32 num_services = -1;
+ UINT8 *p, *np, *op, type;
+ UINT32 raw_used, raw_cur;
+ UINT32 len;
+ UINT32 hdr_len;
+
+ APPL_TRACE_API0( "BTA_JvGetServicesResult");
+ if(p_bta_jv_cfg->p_sdp_db->p_first_rec)
+ {
+ /* the database is valid */
+ num_services = 0;
+ p = p_bta_jv_cfg->p_sdp_db->raw_data;
+ raw_used = p_bta_jv_cfg->p_sdp_db->raw_used;
+ while(raw_used && p)
+ {
+ op = p;
+ type = *p++;
+ np = sdpu_get_len_from_type(p, type, &len);
+ p = np + len;
+ raw_cur = p - op;
+ if(raw_used >= raw_cur)
+ {
+ raw_used -= raw_cur;
+ }
+ else
+ {
+ /* error. can not continue */
+ break;
+ }
+ if(inc_hdr)
+ {
+ hdr_len = np - op;
+ memcpy(TLVs[num_services++], op, len+hdr_len);
+ }
+ else
+ {
+ memcpy(TLVs[num_services++], np, len);
+ }
+ } /* end of while */
+ }
+ return(num_services);
+#endif
+ return 0;
+}
+/*******************************************************************************
+**
+** Function BTA_JvServiceSelect
+**
+** Description This function checks if the SDP database contains the given
+** service UUID. When the operation is complete the
+** tBTA_JV_DM_CBACK callback function will be called with a
+** BTA_JV_SERVICE_SEL_EVT with the length of the service record.
+** If the service is not found or error, -1 is reported.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvServiceSelect(UINT16 uuid)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_SERVICE_SELECT *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvServiceSelect");
+ if ((p_msg = (tBTA_JV_API_SERVICE_SELECT *)GKI_getbuf(sizeof(tBTA_JV_API_SERVICE_SELECT))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_SERVICE_SELECT_EVT;
+ p_msg->uuid = uuid;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvServiceResult
+**
+** Description This function returns the contents of the SDP record from
+** last BTA_JvServiceSelect. The contents will be returned under
+** a TLV (type, len, value) representation in the data buffer
+** provided by the caller.
+**
+** Returns -1, if error. Otherwise, the length of service record.
+**
+*******************************************************************************/
+INT32 BTA_JvServiceResult(UINT8 *TLV)
+{
+ INT32 serv_sel = -1;
+
+ APPL_TRACE_API0( "BTA_JvServiceResult");
+ if(bta_jv_cb.p_sel_raw_data)
+ {
+ serv_sel = bta_jv_cb.sel_len;
+ memcpy(TLV, bta_jv_cb.p_sel_raw_data, serv_sel);
+ }
+
+ return serv_sel;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_JvCreateRecord
+**
+** Description Create a service record in the local SDP database.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_CREATE_RECORD_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvCreateRecordByUser(void *user_data)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_CREATE_RECORD *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvCreateRecordByUser");
+ if ((p_msg = (tBTA_JV_API_CREATE_RECORD *)GKI_getbuf(sizeof(tBTA_JV_API_CREATE_RECORD))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_CREATE_RECORD_EVT;
+ p_msg->user_data = user_data;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvUpdateRecord
+**
+** Description Update a service record in the local SDP database.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_UPDATE_RECORD_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvUpdateRecord(UINT32 handle, UINT16 *p_ids,
+ UINT8 **p_values, INT32 *p_value_sizes, INT32 array_len)
+{
+#if 0
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_UPDATE_RECORD *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvUpdateRecord");
+ if ((p_msg = (tBTA_JV_API_UPDATE_RECORD *)GKI_getbuf(sizeof(tBTA_JV_API_UPDATE_RECORD))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_UPDATE_RECORD_EVT;
+ p_msg->handle = handle;
+ p_msg->p_ids = p_ids;
+ p_msg->p_values = p_values;
+ p_msg->p_value_sizes = p_value_sizes;
+ p_msg->array_len = array_len;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+ return(status);
+#endif
+ return -1;
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvAddAttribute
+**
+** Description Add an attribute to a service record in the local SDP database.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_ADD_ATTR_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvAddAttribute(UINT32 handle, UINT16 attr_id,
+ UINT8 *p_value, INT32 value_size)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_ADD_ATTRIBUTE *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvAddAttribute");
+ if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_ADD_ATTRIBUTE_EVT;
+ p_msg->handle = handle;
+ p_msg->attr_id = attr_id;
+ p_msg->p_value = p_value;
+ p_msg->value_size = value_size;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvDeleteAttribute
+**
+** Description Delete an attribute from a service record in the local SDP database.
+** When the operation is complete the tBTA_JV_DM_CBACK callback
+** function will be called with a BTA_JV_DELETE_ATTR_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvDeleteAttribute(UINT32 handle, UINT16 attr_id)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_ADD_ATTRIBUTE *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvDeleteAttribute");
+ if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_DELETE_ATTRIBUTE_EVT;
+ p_msg->handle = handle;
+ p_msg->attr_id = attr_id;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvDeleteRecord
+**
+** Description Delete a service record in the local SDP database.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvDeleteRecord(UINT32 handle)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_ADD_ATTRIBUTE *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvDeleteRecord");
+ if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_DELETE_RECORD_EVT;
+ p_msg->handle = handle;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvReadRecord
+**
+** Description Read a service record in the local SDP database.
+**
+** Returns -1, if the record is not found.
+** Otherwise, the offset (0 or 1) to start of data in p_data.
+**
+** The size of data copied into p_data is in *p_data_len.
+**
+*******************************************************************************/
+INT32 BTA_JvReadRecord(UINT32 handle, UINT8 *p_data, INT32 *p_data_len)
+{
+ UINT32 sdp_handle;
+
+ sdp_handle = bta_jv_get_sdp_handle(handle);
+
+ if(sdp_handle)
+ {
+ return SDP_ReadRecord(sdp_handle, p_data, p_data_len);
+ }
+
+ return -1;
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capConnect
+**
+** Description Initiate a connection as a L2CAP client to the given BD
+** Address.
+** When the connection is initiated or failed to initiate,
+** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_CL_INIT_EVT
+** When the connection is established or failed,
+** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capConnect(tBTA_SEC sec_mask,
+ tBTA_JV_ROLE role, UINT16 remote_psm, UINT16 rx_mtu,
+ BD_ADDR peer_bd_addr, tBTA_JV_L2CAP_CBACK *p_cback)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_L2CAP_CONNECT *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvL2capConnect");
+ if (p_cback &&
+ (p_msg = (tBTA_JV_API_L2CAP_CONNECT *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_CONNECT))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_L2CAP_CONNECT_EVT;
+ p_msg->sec_mask = sec_mask;
+ p_msg->role = role;
+ p_msg->remote_psm = remote_psm;
+ p_msg->rx_mtu = rx_mtu;
+ memcpy(p_msg->peer_bd_addr, peer_bd_addr, sizeof(BD_ADDR));
+ p_msg->p_cback = p_cback;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capClose
+**
+** Description This function closes an L2CAP client connection
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capClose(UINT32 handle)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_L2CAP_CLOSE *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvL2capClose");
+ if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback &&
+ (p_msg = (tBTA_JV_API_L2CAP_CLOSE *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_CLOSE))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_L2CAP_CLOSE_EVT;
+ p_msg->handle = handle;
+ p_msg->p_cb = &bta_jv_cb.l2c_cb[handle];
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capStartServer
+**
+** Description This function starts an L2CAP server and listens for an L2CAP
+** connection from a remote Bluetooth device. When the server
+** is started successfully, tBTA_JV_L2CAP_CBACK is called with
+** BTA_JV_L2CAP_START_EVT. When the connection is established,
+** tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capStartServer(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+ UINT16 local_psm, UINT16 rx_mtu,
+ tBTA_JV_L2CAP_CBACK *p_cback)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_L2CAP_SERVER *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvL2capStartServer");
+ if (p_cback &&
+ (p_msg = (tBTA_JV_API_L2CAP_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_SERVER))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_L2CAP_START_SERVER_EVT;
+ p_msg->sec_mask = sec_mask;
+ p_msg->role = role;
+ p_msg->local_psm = local_psm;
+ p_msg->rx_mtu = rx_mtu;
+ p_msg->p_cback = p_cback;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capStopServer
+**
+** Description This function stops the L2CAP server. If the server has an
+** active connection, it would be closed.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capStopServer(UINT16 local_psm)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_L2CAP_SERVER *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvL2capStopServer");
+ if ((p_msg = (tBTA_JV_API_L2CAP_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_SERVER))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_L2CAP_STOP_SERVER_EVT;
+ p_msg->local_psm = local_psm;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capRead
+**
+** Description This function reads data from an L2CAP connecti;
+ tBTA_JV_RFC_CB *p_cb = rc->p_cb;
+on
+** When the operation is complete, tBTA_JV_L2CAP_CBACK is
+** called with BTA_JV_L2CAP_READ_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capRead(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len)
+{
+#if 0
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+#if SDP_FOR_JV_INCLUDED == TRUE
+ tBTA_JV_API_L2CAP_READ *p_msg;
+#endif
+ tBTA_JV_L2CAP_READ evt_data;
+
+ APPL_TRACE_API0( "BTA_JvL2capRead");
+
+#if SDP_FOR_JV_INCLUDED == TRUE
+ if(BTA_JV_L2C_FOR_SDP_HDL == handle)
+ {
+ if (bta_jv_cb.l2c_cb[handle].p_cback &&
+ (p_msg = (tBTA_JV_API_L2CAP_READ *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_READ))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_L2CAP_READ_EVT;
+ p_msg->handle = handle;
+ p_msg->req_id = req_id;
+ p_msg->p_data = p_data;
+ p_msg->len = len;
+ p_msg->p_cback = bta_jv_cb.l2c_cb[handle].p_cback;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+ }
+ else
+#endif
+ if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback)
+ {
+ status = BTA_JV_SUCCESS;
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = handle;
+ evt_data.req_id = req_id;
+ evt_data.p_data = p_data;
+ evt_data.len = 0;
+
+ if (BT_PASS == GAP_ConnReadData((UINT16)handle, p_data, len, &evt_data.len))
+ {
+ evt_data.status = BTA_JV_SUCCESS;
+ }
+ bta_jv_cb.l2c_cb[handle].p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data);
+ }
+
+ return(status);
+#endif
+ return -1;
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capReceive
+**
+** Description This function reads data from an L2CAP connection
+** When the operation is complete, tBTA_JV_L2CAP_CBACK is
+** called with BTA_JV_L2CAP_RECEIVE_EVT.
+** If there are more data queued in L2CAP than len, the extra data will be discarded.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capReceive(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len)
+{
+#if 0
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_L2CAP_RECEIVE evt_data;
+ UINT32 left_over = 0;
+ UINT16 max_len, read_len;
+
+ APPL_TRACE_API0( "BTA_JvL2capReceive");
+
+ if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback)
+ {
+ status = BTA_JV_SUCCESS;
+ evt_data.status = BTA_JV_FAILURE;
+ evt_data.handle = handle;
+ evt_data.req_id = req_id;
+ evt_data.p_data = p_data;
+ evt_data.len = 0;
+
+ if (BT_PASS == GAP_ConnReadData((UINT16)handle, p_data, len, &evt_data.len))
+ {
+ evt_data.status = BTA_JV_SUCCESS;
+ GAP_GetRxQueueCnt ((UINT16)handle, &left_over);
+ while (left_over)
+ {
+ max_len = (left_over > 0xFFFF)?0xFFFF:left_over;
+ GAP_ConnReadData ((UINT16)handle, NULL, max_len, &read_len);
+ left_over -= read_len;
+ }
+ }
+ bta_jv_cb.l2c_cb[handle].p_cback(BTA_JV_L2CAP_RECEIVE_EVT, (tBTA_JV *)&evt_data);
+ }
+
+ return(status);
+#endif
+ return -1;
+}
+/*******************************************************************************
+**
+** Function BTA_JvL2capReady
+**
+** Description This function determined if there is data to read from
+** an L2CAP connection
+**
+** Returns BTA_JV_SUCCESS, if data queue size is in *p_data_size.
+** BTA_JV_FAILURE, if error.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capReady(UINT32 handle, UINT32 *p_data_size)
+{
+#if 0
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+
+ APPL_TRACE_API1( "BTA_JvL2capReady: %d", handle);
+ if (p_data_size && handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback)
+ {
+ *p_data_size = 0;
+#if SDP_FOR_JV_INCLUDED == TRUE
+ if(BTA_JV_L2C_FOR_SDP_HDL == handle)
+ {
+ *p_data_size = bta_jv_cb.sdp_data_size;
+ status = BTA_JV_SUCCESS;
+ }
+ else
+#endif
+ if(BT_PASS == GAP_GetRxQueueCnt((UINT16)handle, p_data_size) )
+ {
+ status = BTA_JV_SUCCESS;
+ }
+ }
+
+ return(status);
+#endif
+ return -1;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_JvL2capWrite
+**
+** Description This function writes data to an L2CAP connection
+** When the operation is complete, tBTA_JV_L2CAP_CBACK is
+** called with BTA_JV_L2CAP_WRITE_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capWrite(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_L2CAP_WRITE *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvL2capWrite");
+ if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback &&
+ (p_msg = (tBTA_JV_API_L2CAP_WRITE *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_WRITE))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_L2CAP_WRITE_EVT;
+ p_msg->handle = handle;
+ p_msg->req_id = req_id;
+ p_msg->p_data = p_data;
+ p_msg->p_cb = &bta_jv_cb.l2c_cb[handle];
+ p_msg->len = len;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommConnect
+**
+** Description This function makes an RFCOMM conection to a remote BD
+** Address.
+** When the connection is initiated or failed to initiate,
+** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CL_INIT_EVT
+** When the connection is established or failed,
+** tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_OPEN_EVT
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask,
+ tBTA_JV_ROLE role, UINT8 remote_scn, BD_ADDR peer_bd_addr,
+ tBTA_JV_RFCOMM_CBACK *p_cback, void* user_data)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_RFCOMM_CONNECT *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvRfcommConnect");
+ if (p_cback &&
+ (p_msg = (tBTA_JV_API_RFCOMM_CONNECT *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_CONNECT))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_RFCOMM_CONNECT_EVT;
+ p_msg->sec_mask = sec_mask;
+ p_msg->role = role;
+ p_msg->remote_scn = remote_scn;
+ memcpy(p_msg->peer_bd_addr, peer_bd_addr, sizeof(BD_ADDR));
+ p_msg->p_cback = p_cback;
+ p_msg->user_data = user_data;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommClose
+**
+** Description This function closes an RFCOMM connection
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_RFCOMM_CLOSE *p_msg;
+ UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+ UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+ APPL_TRACE_API0( "BTA_JvRfcommClose");
+ if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+ si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si] &&
+ (p_msg = (tBTA_JV_API_RFCOMM_CLOSE *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_CLOSE))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_RFCOMM_CLOSE_EVT;
+ p_msg->handle = handle;
+ p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
+ p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommStartServer
+**
+** Description This function starts listening for an RFCOMM connection
+** request from a remote Bluetooth device. When the server is
+** started successfully, tBTA_JV_RFCOMM_CBACK is called
+** with BTA_JV_RFCOMM_START_EVT.
+** When the connection is established, tBTA_JV_RFCOMM_CBACK
+** is called with BTA_JV_RFCOMM_OPEN_EVT.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask,
+ tBTA_JV_ROLE role, UINT8 local_scn, UINT8 max_session,
+ tBTA_JV_RFCOMM_CBACK *p_cback, void* user_data)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_RFCOMM_SERVER *p_msg;
+
+ APPL_TRACE_API0( "BTA_JvRfcommStartServer");
+ if (p_cback &&
+ (p_msg = (tBTA_JV_API_RFCOMM_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_SERVER))) != NULL)
+ {
+ if (max_session == 0)
+ max_session = 1;
+ if (max_session > BTA_JV_MAX_RFC_SR_SESSION)
+ {
+ APPL_TRACE_DEBUG2( "max_session is too big. use max (%d)", max_session, BTA_JV_MAX_RFC_SR_SESSION);
+ max_session = BTA_JV_MAX_RFC_SR_SESSION;
+ }
+ p_msg->hdr.event = BTA_JV_API_RFCOMM_START_SERVER_EVT;
+ p_msg->sec_mask = sec_mask;
+ p_msg->role = role;
+ p_msg->local_scn = local_scn;
+ p_msg->max_session = max_session;
+ p_msg->p_cback = p_cback;
+ p_msg->user_data = user_data; //caller's private data
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommStopServer
+**
+** Description This function stops the RFCOMM server. If the server has an
+** active connection, it would be closed.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommStopServer(UINT32 handle)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_RFCOMM_SERVER *p_msg;
+ APPL_TRACE_API0( "BTA_JvRfcommStopServer");
+ if ((p_msg = (tBTA_JV_API_RFCOMM_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_SERVER))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_RFCOMM_STOP_SERVER_EVT;
+ p_msg->rfc_handle = handle;
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommRead
+**
+** Description This function reads data from an RFCOMM connection
+** The actual size of data read is returned in p_len.
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommRead(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_RFCOMM_READ *p_msg;
+ UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+ UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+ APPL_TRACE_API0( "BTA_JvRfcommRead");
+ if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+ si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si] &&
+ (p_msg = (tBTA_JV_API_RFCOMM_READ *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_READ))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_RFCOMM_READ_EVT;
+ p_msg->handle = handle;
+ p_msg->req_id = req_id;
+ p_msg->p_data = p_data;
+ p_msg->len = len;
+ p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
+ p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommGetPortHdl
+**
+** Description This function fetches the rfcomm port handle
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle)
+{
+ UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+ UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+ if (hi < BTA_JV_MAX_RFC_CONN &&
+ si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si])
+ return bta_jv_cb.port_cb[bta_jv_cb.rfc_cb[hi].rfc_hdl[si] - 1].port_handle;
+ else
+ return 0xffff;
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommReady
+**
+** Description This function determined if there is data to read from
+** an RFCOMM connection
+**
+** Returns BTA_JV_SUCCESS, if data queue size is in *p_data_size.
+** BTA_JV_FAILURE, if error.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommReady(UINT32 handle, UINT32 *p_data_size)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ UINT16 size = 0;
+ UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+ UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+ APPL_TRACE_API0( "BTA_JvRfcommReady");
+ if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+ si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si])
+ {
+ if(PORT_GetRxQueueCnt(bta_jv_cb.rfc_cb[hi].rfc_hdl[si], &size) == PORT_SUCCESS)
+ {
+ status = BTA_JV_SUCCESS;
+ }
+ }
+ *p_data_size = size;
+ return(status);
+}
+
+/*******************************************************************************
+**
+** Function BTA_JvRfcommWrite
+**
+** Description This function writes data to an RFCOMM connection
+**
+** Returns BTA_JV_SUCCESS, if the request is being processed.
+** BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id)
+{
+ tBTA_JV_STATUS status = BTA_JV_FAILURE;
+ tBTA_JV_API_RFCOMM_WRITE *p_msg;
+ UINT32 hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+ UINT32 si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+ APPL_TRACE_API0( "BTA_JvRfcommWrite");
+ APPL_TRACE_DEBUG3( "handle:0x%x, hi:%d, si:%d", handle, hi, si);
+ if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+ si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si] &&
+ (p_msg = (tBTA_JV_API_RFCOMM_WRITE *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_WRITE))) != NULL)
+ {
+ p_msg->hdr.event = BTA_JV_API_RFCOMM_WRITE_EVT;
+ p_msg->handle = handle;
+ p_msg->req_id = req_id;
+ p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
+ p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
+ APPL_TRACE_API0( "write ok");
+ bta_sys_sendmsg(p_msg);
+ status = BTA_JV_SUCCESS;
+ }
+
+ return(status);
+}
+
diff --git a/bta/jv/bta_jv_cfg.c b/bta/jv/bta_jv_cfg.c
new file mode 100644
index 0000000..675801f
--- /dev/null
+++ b/bta/jv/bta_jv_cfg.c
@@ -0,0 +1,58 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains compile-time configurable constants for advanced
+ * audio
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_jv_api.h"
+
+#ifndef BTA_JV_SDP_DB_SIZE
+#define BTA_JV_SDP_DB_SIZE 4500
+#endif
+
+#ifndef BTA_JV_SDP_RAW_DATA_SIZE
+#define BTA_JV_SDP_RAW_DATA_SIZE 1800
+#endif
+
+/* The platform may choose to use dynamic memory for these data buffers.
+ * p_bta_jv_cfg->p_sdp_db must be allocated/stay allocated
+ * between BTA_JvEnable and BTA_JvDisable
+ * p_bta_jv_cfg->p_sdp_raw_data can be allocated before calling BTA_JvStartDiscovery
+ * it can be de-allocated after the last call to access the database */
+static UINT8 bta_jv_sdp_raw_data[BTA_JV_SDP_RAW_DATA_SIZE];
+static UINT8 bta_jv_sdp_db_data[BTA_JV_SDP_DB_SIZE];
+
+/* JV configuration structure */
+const tBTA_JV_CFG bta_jv_cfg =
+{
+ BTA_JV_SDP_RAW_DATA_SIZE, /* The size of p_sdp_raw_data */
+ BTA_JV_SDP_DB_SIZE, /* The size of p_sdp_db_data */
+ bta_jv_sdp_raw_data, /* The data buffer to keep raw data */
+ (tSDP_DISCOVERY_DB *)bta_jv_sdp_db_data /* The data buffer to keep SDP database */
+};
+
+tBTA_JV_CFG *p_bta_jv_cfg = (tBTA_JV_CFG *) &bta_jv_cfg;
+
+
diff --git a/bta/jv/bta_jv_int.h b/bta/jv/bta_jv_int.h
new file mode 100644
index 0000000..5a0aaed
--- /dev/null
+++ b/bta/jv/bta_jv_int.h
@@ -0,0 +1,461 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2006-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private interface file for the BTA Java I/F
+ *
+ ******************************************************************************/
+#ifndef BTA_JV_INT_H
+#define BTA_JV_INT_H
+
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_jv_api.h"
+#include "rfcdefs.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_JV_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_JV),
+ BTA_JV_API_DISABLE_EVT,
+ BTA_JV_API_SET_DISCOVERABILITY_EVT,
+ BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT,
+ BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT,
+ BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT,
+ BTA_JV_API_SET_SERVICE_CLASS_EVT,
+ BTA_JV_API_SET_ENCRYPTION_EVT,
+ BTA_JV_API_GET_SCN_EVT,
+ BTA_JV_API_FREE_SCN_EVT,
+ BTA_JV_API_START_DISCOVERY_EVT,
+ BTA_JV_API_CANCEL_DISCOVERY_EVT,
+ BTA_JV_API_GET_SERVICES_LENGTH_EVT,
+ BTA_JV_API_SERVICE_SELECT_EVT,
+ BTA_JV_API_CREATE_RECORD_EVT,
+ BTA_JV_API_UPDATE_RECORD_EVT,
+ BTA_JV_API_ADD_ATTRIBUTE_EVT,
+ BTA_JV_API_DELETE_ATTRIBUTE_EVT,
+ BTA_JV_API_DELETE_RECORD_EVT,
+ BTA_JV_API_L2CAP_CONNECT_EVT,
+ BTA_JV_API_L2CAP_CLOSE_EVT,
+ BTA_JV_API_L2CAP_START_SERVER_EVT,
+ BTA_JV_API_L2CAP_STOP_SERVER_EVT,
+ BTA_JV_API_L2CAP_READ_EVT,
+ BTA_JV_API_L2CAP_WRITE_EVT,
+ BTA_JV_API_RFCOMM_CONNECT_EVT,
+ BTA_JV_API_RFCOMM_CLOSE_EVT,
+ BTA_JV_API_RFCOMM_START_SERVER_EVT,
+ BTA_JV_API_RFCOMM_STOP_SERVER_EVT,
+ BTA_JV_API_RFCOMM_READ_EVT,
+ BTA_JV_API_RFCOMM_WRITE_EVT,
+ BTA_JV_MAX_INT_EVT
+};
+
+/* data type for BTA_JV_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_JV_DM_CBACK *p_cback;
+} tBTA_JV_API_ENABLE;
+
+/* data type for BTA_JV_API_SET_DISCOVERABILITY_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_JV_DISC disc_mode;
+} tBTA_JV_API_SET_DISCOVERABILITY;
+
+
+/* data type for BTA_JV_API_SET_SERVICE_CLASS_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT32 service;
+} tBTA_JV_API_SET_SERVICE_CLASS;
+
+/* data type for BTA_JV_API_SET_ENCRYPTION_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_JV_API_SET_ENCRYPTION;
+
+/* data type for BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_JV_API_GET_REMOTE_NAME;
+
+/* data type for BTA_JV_API_START_DISCOVERY_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ UINT16 num_uuid;
+ tSDP_UUID uuid_list[BTA_JV_MAX_UUIDS];
+ UINT16 num_attr;
+ UINT16 attr_list[BTA_JV_MAX_ATTRS];
+ void *user_data; /* piggyback caller's private data*/
+} tBTA_JV_API_START_DISCOVERY;
+
+/* data type for BTA_JV_API_CANCEL_DISCOVERY_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ void *user_data; /* piggyback caller's private data*/
+} tBTA_JV_API_CANCEL_DISCOVERY;
+
+
+/* data type for BTA_JV_API_GET_SERVICES_LENGTH_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 *p_services_len;
+ BOOLEAN inc_hdr;
+} tBTA_JV_API_GET_SERVICES_LENGTH;
+
+/* data type for BTA_JV_API_GET_SERVICE_RESULT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 **TLVs;
+} tBTA_JV_API_GET_SERVICE_RESULT;
+
+/* data type for BTA_JV_API_SERVICE_SELECT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 uuid;
+} tBTA_JV_API_SERVICE_SELECT;
+
+enum
+{
+ BTA_JV_ST_NONE = 0,
+ BTA_JV_ST_CL_OPENING,
+ BTA_JV_ST_CL_OPEN,
+ BTA_JV_ST_CL_CLOSING,
+ BTA_JV_ST_SR_LISTEN,
+ BTA_JV_ST_SR_OPEN,
+ BTA_JV_ST_SR_CLOSING
+} ;
+typedef UINT8 tBTA_JV_STATE;
+#define BTA_JV_ST_CL_MAX BTA_JV_ST_CL_CLOSING
+
+/* JV L2CAP control block */
+typedef struct
+{
+ tBTA_JV_L2CAP_CBACK *p_cback; /* the callback function */
+ UINT16 psm; /* the psm used for this server connection */
+ tBTA_JV_STATE state; /* the state of this control block */
+ tBTA_SERVICE_ID sec_id; /* service id */
+ UINT16 handle; /* the handle reported to java app (same as gap handle) */
+ BOOLEAN cong; /* TRUE, if congested */
+} tBTA_JV_L2C_CB;
+
+#define BTA_JV_RFC_HDL_MASK 0xFF
+#define BTA_JV_RFC_HDL_TO_SIDX(r) (((r)&0xFF00) >> 8)
+#define BTA_JV_RFC_H_S_TO_HDL(h, s) ((h)|(s<<8))
+
+/* port control block */
+typedef struct
+{
+ UINT32 handle; /* the rfcomm session handle at jv */
+ UINT16 port_handle; /* port handle */
+ tBTA_JV_STATE state; /* the state of this control block */
+ UINT8 max_sess; /* max sessions */
+ void *user_data; /* piggyback caller's private data*/
+ BOOLEAN cong; /* TRUE, if congested */
+} tBTA_JV_PCB;
+
+/* JV RFCOMM control block */
+typedef struct
+{
+ tBTA_JV_RFCOMM_CBACK *p_cback; /* the callback function */
+ UINT16 rfc_hdl[BTA_JV_MAX_RFC_SR_SESSION];
+ tBTA_SERVICE_ID sec_id; /* service id */
+ UINT8 handle; /* index: the handle reported to java app */
+ UINT8 scn; /* the scn of the server */
+ UINT8 max_sess; /* max sessions */
+} tBTA_JV_RFC_CB;
+
+/* data type for BTA_JV_API_L2CAP_CONNECT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_SEC sec_mask;
+ tBTA_JV_ROLE role;
+ UINT16 remote_psm;
+ UINT16 rx_mtu;
+ BD_ADDR peer_bd_addr;
+ tBTA_JV_L2CAP_CBACK *p_cback;
+} tBTA_JV_API_L2CAP_CONNECT;
+
+/* data type for BTA_JV_API_L2CAP_SERVER_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_SEC sec_mask;
+ tBTA_JV_ROLE role;
+ UINT16 local_psm;
+ UINT16 rx_mtu;
+ tBTA_JV_L2CAP_CBACK *p_cback;
+} tBTA_JV_API_L2CAP_SERVER;
+
+/* data type for BTA_JV_API_L2CAP_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 handle;
+ tBTA_JV_L2C_CB *p_cb;
+} tBTA_JV_API_L2CAP_CLOSE;
+
+/* data type for BTA_JV_API_L2CAP_READ_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 handle;
+ UINT32 req_id;
+ tBTA_JV_L2CAP_CBACK *p_cback;
+ UINT8* p_data;
+ UINT16 len;
+} tBTA_JV_API_L2CAP_READ;
+
+/* data type for BTA_JV_API_L2CAP_WRITE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 handle;
+ UINT32 req_id;
+ tBTA_JV_L2C_CB *p_cb;
+ UINT8 *p_data;
+ UINT16 len;
+} tBTA_JV_API_L2CAP_WRITE;
+
+/* data type for BTA_JV_API_RFCOMM_CONNECT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_SEC sec_mask;
+ tBTA_JV_ROLE role;
+ UINT8 remote_scn;
+ BD_ADDR peer_bd_addr;
+ tBTA_JV_RFCOMM_CBACK *p_cback;
+ void *user_data;
+} tBTA_JV_API_RFCOMM_CONNECT;
+
+/* data type for BTA_JV_API_RFCOMM_SERVER_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_SEC sec_mask;
+ tBTA_JV_ROLE role;
+ UINT8 local_scn;
+ UINT8 max_session;
+ int rfc_handle;
+ tBTA_JV_RFCOMM_CBACK *p_cback;
+ void *user_data;
+} tBTA_JV_API_RFCOMM_SERVER;
+
+/* data type for BTA_JV_API_RFCOMM_READ_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 handle;
+ UINT32 req_id;
+ UINT8 *p_data;
+ UINT16 len;
+ tBTA_JV_RFC_CB *p_cb;
+ tBTA_JV_PCB *p_pcb;
+} tBTA_JV_API_RFCOMM_READ;
+
+/* data type for BTA_JV_API_RFCOMM_WRITE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 handle;
+ UINT32 req_id;
+ UINT8 *p_data;
+ int len;
+ tBTA_JV_RFC_CB *p_cb;
+ tBTA_JV_PCB *p_pcb;
+} tBTA_JV_API_RFCOMM_WRITE;
+
+/* data type for BTA_JV_API_RFCOMM_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT16 handle;
+ tBTA_JV_RFC_CB *p_cb;
+ tBTA_JV_PCB *p_pcb;
+} tBTA_JV_API_RFCOMM_CLOSE;
+
+/* data type for BTA_JV_API_CREATE_RECORD_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ void *user_data;
+} tBTA_JV_API_CREATE_RECORD;
+
+/* data type for BTA_JV_API_UPDATE_RECORD_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT32 handle;
+ UINT16 *p_ids;
+ UINT8 **p_values;
+ INT32 *p_value_sizes;
+ INT32 array_len;
+} tBTA_JV_API_UPDATE_RECORD;
+
+/* data type for BTA_JV_API_ADD_ATTRIBUTE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT32 handle;
+ UINT16 attr_id;
+ UINT8 *p_value;
+ INT32 value_size;
+} tBTA_JV_API_ADD_ATTRIBUTE;
+
+/* data type for BTA_JV_API_FREE_SCN_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 scn;
+} tBTA_JV_API_FREE_SCN;
+/* union of all data types */
+typedef union
+{
+ /* GKI event buffer header */
+ BT_HDR hdr;
+ tBTA_JV_API_ENABLE enable;
+ tBTA_JV_API_SET_DISCOVERABILITY set_discoverability;
+ tBTA_JV_API_GET_REMOTE_NAME get_rmt_name;
+ tBTA_JV_API_SET_SERVICE_CLASS set_service;
+ tBTA_JV_API_SET_ENCRYPTION set_encrypt;
+ tBTA_JV_API_START_DISCOVERY start_discovery;
+ tBTA_JV_API_CANCEL_DISCOVERY cancel_discovery;
+ tBTA_JV_API_GET_SERVICES_LENGTH get_services_length;
+ tBTA_JV_API_GET_SERVICE_RESULT get_service_result;
+ tBTA_JV_API_SERVICE_SELECT service_select;
+ tBTA_JV_API_FREE_SCN free_scn;
+ tBTA_JV_API_CREATE_RECORD create_record;
+ tBTA_JV_API_UPDATE_RECORD update_record;
+ tBTA_JV_API_ADD_ATTRIBUTE add_attr;
+ tBTA_JV_API_L2CAP_CONNECT l2cap_connect;
+ tBTA_JV_API_L2CAP_READ l2cap_read;
+ tBTA_JV_API_L2CAP_WRITE l2cap_write;
+ tBTA_JV_API_L2CAP_CLOSE l2cap_close;
+ tBTA_JV_API_L2CAP_SERVER l2cap_server;
+ tBTA_JV_API_RFCOMM_CONNECT rfcomm_connect;
+ tBTA_JV_API_RFCOMM_READ rfcomm_read;
+ tBTA_JV_API_RFCOMM_WRITE rfcomm_write;
+ tBTA_JV_API_RFCOMM_CLOSE rfcomm_close;
+ tBTA_JV_API_RFCOMM_SERVER rfcomm_server;
+} tBTA_JV_MSG;
+
+#if SDP_FOR_JV_INCLUDED == TRUE
+#define BTA_JV_L2C_FOR_SDP_HDL GAP_MAX_CONNECTIONS
+#endif
+
+/* JV control block */
+typedef struct
+{
+#if SDP_FOR_JV_INCLUDED == TRUE
+ UINT32 sdp_for_jv; /* The SDP client connection handle */
+ UINT32 sdp_data_size; /* the data len */
+#endif
+ /* the SDP handle reported to JV user is the (index + 1) to sdp_handle[].
+ * if sdp_handle[i]==0, it's not used.
+ * otherwise sdp_handle[i] is the stack SDP handle. */
+ UINT32 sdp_handle[BTA_JV_MAX_SDP_REC]; /* SDP records created */
+ UINT8 *p_sel_raw_data;/* the raw data of last service select */
+ INT32 sel_len; /* the SDP record size of last service select */
+ tBTA_JV_DM_CBACK *p_dm_cback;
+ tBTA_JV_L2C_CB l2c_cb[BTA_JV_MAX_L2C_CONN]; /* index is GAP handle (index) */
+ tBTA_JV_RFC_CB rfc_cb[BTA_JV_MAX_RFC_CONN];
+ tBTA_JV_PCB port_cb[MAX_RFC_PORTS]; /* index of this array is the port_handle, */
+ UINT8 sec_id[BTA_JV_NUM_SERVICE_ID]; /* service ID */
+ BOOLEAN scn[BTA_JV_MAX_SCN]; /* SCN allocated by java */
+ UINT8 sdp_active; /* see BTA_JV_SDP_ACT_* */
+ tSDP_UUID uuid; /* current uuid of sdp discovery*/
+ void *user_data; /* piggyback user data*/
+} tBTA_JV_CB;
+
+enum
+{
+ BTA_JV_SDP_ACT_NONE = 0,
+ BTA_JV_SDP_ACT_YES, /* waiting for SDP result */
+ BTA_JV_SDP_ACT_CANCEL /* waiting for cancel complete */
+};
+
+/* JV control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_JV_CB bta_jv_cb;
+#else
+extern tBTA_JV_CB *bta_jv_cb_ptr;
+#define bta_jv_cb (*bta_jv_cb_ptr)
+#endif
+
+/* config struct */
+extern tBTA_JV_CFG *p_bta_jv_cfg;
+
+/* this is defined in stack/sdp. used by bta jv */
+extern UINT8 *sdpu_get_len_from_type (UINT8 *p, UINT8 type, UINT32 *p_len);
+
+extern BOOLEAN bta_jv_sm_execute(BT_HDR *p_msg);
+
+extern UINT32 bta_jv_get_sdp_handle(UINT32 sdp_id);
+extern void bta_jv_enable (tBTA_JV_MSG *p_data);
+extern void bta_jv_disable (tBTA_JV_MSG *p_data);
+extern void bta_jv_set_discoverability (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_local_device_addr (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_local_device_name (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_remote_device_name (tBTA_JV_MSG *p_data);
+extern void bta_jv_set_service_class (tBTA_JV_MSG *p_data);
+extern void bta_jv_set_encryption (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_scn (tBTA_JV_MSG *p_data);
+extern void bta_jv_free_scn (tBTA_JV_MSG *p_data);
+extern void bta_jv_start_discovery (tBTA_JV_MSG *p_data);
+extern void bta_jv_cancel_discovery (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_services_length (tBTA_JV_MSG *p_data);
+extern void bta_jv_service_select (tBTA_JV_MSG *p_data);
+extern void bta_jv_create_record (tBTA_JV_MSG *p_data);
+extern void bta_jv_update_record (tBTA_JV_MSG *p_data);
+extern void bta_jv_add_attribute (tBTA_JV_MSG *p_data);
+extern void bta_jv_delete_attribute (tBTA_JV_MSG *p_data);
+extern void bta_jv_delete_record (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_connect (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_close (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_start_server (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_stop_server (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_read (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_write (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_connect (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_close (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_start_server (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_stop_server (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_read (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_write (tBTA_JV_MSG *p_data);
+
+#endif /* BTA_JV_INT_H */
diff --git a/bta/jv/bta_jv_main.c b/bta/jv/bta_jv_main.c
new file mode 100644
index 0000000..0cba56b
--- /dev/null
+++ b/bta/jv/bta_jv_main.c
@@ -0,0 +1,103 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the main implementation file for the BTA Java I/F
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_jv_api.h"
+#include "bta_jv_int.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_JV_CB bta_jv_cb;
+#endif
+
+/* state machine action enumeration list */
+#define BTA_JV_NUM_ACTIONS (BTA_JV_MAX_INT_EVT & 0x00ff)
+
+/* type for action functions */
+typedef void (*tBTA_JV_ACTION)(tBTA_JV_MSG *p_data);
+
+/* action function list */
+const tBTA_JV_ACTION bta_jv_action[] =
+{
+ bta_jv_enable, /* BTA_JV_API_ENABLE_EVT */
+ bta_jv_disable, /* BTA_JV_API_DISABLE_EVT */
+ bta_jv_set_discoverability, /* BTA_JV_API_SET_DISCOVERABILITY_EVT */
+ bta_jv_get_local_device_addr, /* BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT */
+ bta_jv_get_local_device_name, /* BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT */
+ bta_jv_get_remote_device_name, /* BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT */
+ bta_jv_set_service_class, /* BTA_JV_API_SET_SERVICE_CLASS_EVT */
+ bta_jv_set_encryption, /* BTA_JV_API_SET_ENCRYPTION_EVT */
+ bta_jv_get_scn, /* BTA_JV_API_GET_SCN_EVT */
+ bta_jv_free_scn, /* BTA_JV_API_FREE_SCN_EVT */
+ bta_jv_start_discovery, /* BTA_JV_API_START_DISCOVERY_EVT */
+ bta_jv_cancel_discovery, /* BTA_JV_API_CANCEL_DISCOVERY_EVT */
+ bta_jv_get_services_length, /* BTA_JV_API_GET_SERVICES_LENGTH_EVT */
+ bta_jv_service_select, /* BTA_JV_API_SERVICE_SELECT_EVT */
+ bta_jv_create_record, /* BTA_JV_API_CREATE_RECORD_EVT */
+ bta_jv_update_record, /* BTA_JV_API_UPDATE_RECORD_EVT */
+ bta_jv_add_attribute, /* BTA_JV_API_ADD_ATTRIBUTE_EVT */
+ bta_jv_delete_attribute, /* BTA_JV_API_DELETE_ATTRIBUTE_EVT */
+ bta_jv_delete_record, /* BTA_JV_API_DELETE_RECORD_EVT */
+ bta_jv_l2cap_connect, /* BTA_JV_API_L2CAP_CONNECT_EVT */
+ bta_jv_l2cap_close, /* BTA_JV_API_L2CAP_CLOSE_EVT */
+ bta_jv_l2cap_start_server, /* BTA_JV_API_L2CAP_START_SERVER_EVT */
+ bta_jv_l2cap_stop_server, /* BTA_JV_API_L2CAP_STOP_SERVER_EVT */
+ bta_jv_l2cap_read, /* BTA_JV_API_L2CAP_READ_EVT */
+ bta_jv_l2cap_write, /* BTA_JV_API_L2CAP_WRITE_EVT */
+ bta_jv_rfcomm_connect, /* BTA_JV_API_RFCOMM_CONNECT_EVT */
+ bta_jv_rfcomm_close, /* BTA_JV_API_RFCOMM_CLOSE_EVT */
+ bta_jv_rfcomm_start_server, /* BTA_JV_API_RFCOMM_START_SERVER_EVT */
+ bta_jv_rfcomm_stop_server, /* BTA_JV_API_RFCOMM_STOP_SERVER_EVT */
+ bta_jv_rfcomm_read, /* BTA_JV_API_RFCOMM_READ_EVT */
+ bta_jv_rfcomm_write /* BTA_JV_API_RFCOMM_WRITE_EVT */
+};
+
+/*******************************************************************************
+**
+** Function bta_jv_sm_execute
+**
+** Description State machine event handling function for JV
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_jv_sm_execute(BT_HDR *p_msg)
+{
+ BOOLEAN ret = FALSE;
+ UINT16 action = (p_msg->event & 0x00ff);
+ /* execute action functions */
+
+ if(action < BTA_JV_NUM_ACTIONS)
+ {
+ (*bta_jv_action[action])((tBTA_JV_MSG*)p_msg);
+ ret = TRUE;
+ }
+
+ return(ret);
+}
diff --git a/bta/pan/bta_pan_act.c b/bta/pan/bta_pan_act.c
new file mode 100644
index 0000000..b29920f
--- /dev/null
+++ b/bta/pan/bta_pan_act.c
@@ -0,0 +1,728 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the pan action functions for the state machine.
+ *
+ ******************************************************************************/
+
+#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);
+
+ set_role.role = p_data->api_set_role.role;
+ 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.status = BTA_PAN_SUCCESS;
+ }
+ /* 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.status = BTA_PAN_FAIL;
+ }
+ 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..6588230
--- /dev/null
+++ b/bta/pan/bta_pan_api.c
@@ -0,0 +1,214 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation of the API for PAN subsystem of BTA,
+ * Broadcom's Bluetooth application layer for mobile phones.
+ *
+ ******************************************************************************/
+
+#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..f8e5832
--- /dev/null
+++ b/bta/pan/bta_pan_ci.c
@@ -0,0 +1,260 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation file for data gateway call-in functions.
+ *
+ ******************************************************************************/
+
+#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..1667e57
--- /dev/null
+++ b/bta/pan/bta_pan_int.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private interface file for the BTA data gateway.
+ *
+ ******************************************************************************/
+#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..add1c7c
--- /dev/null
+++ b/bta/pan/bta_pan_main.c
@@ -0,0 +1,421 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains the PAN main functions and state machine.
+ *
+ ******************************************************************************/
+
+#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 */
diff --git a/bta/pb/bta_pbs_cfg.c b/bta/pb/bta_pbs_cfg.c
new file mode 100644
index 0000000..b2782fb
--- /dev/null
+++ b/bta/pb/bta_pbs_cfg.c
@@ -0,0 +1,51 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains compile-time configurable constants for the BTA Phone
+ * Book Access Server.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include "bta_pbs_int.h"
+
+/* Realm Character Set */
+#ifndef BTA_PBS_REALM_CHARSET
+#define BTA_PBS_REALM_CHARSET 0 /* ASCII */
+#endif
+
+/* Specifies whether or not client's user id is required during obex authentication */
+#ifndef BTA_PBS_USERID_REQ
+#define BTA_PBS_USERID_REQ FALSE
+#endif
+
+const tBTA_PBS_CFG bta_pbs_cfg =
+{
+ BTA_PBS_REALM_CHARSET, /* Server only */
+ BTA_PBS_USERID_REQ, /* Server only */
+ (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),
+ BTA_PBS_REPOSIT_LOCAL,
+};
+
+tBTA_PBS_CFG *p_bta_pbs_cfg = (tBTA_PBS_CFG *)&bta_pbs_cfg;
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_int.h b/bta/pb/bta_pbs_int.h
new file mode 100644
index 0000000..a4fce2b
--- /dev/null
+++ b/bta/pb/bta_pbs_int.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private file for the phone book access server (PBS).
+ *
+ ******************************************************************************/
+#ifndef BTA_PBS_INT_H
+#define BTA_PBS_INT_H
+
+#include "bt_target.h"
+#include "bta_pbs_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+#define BTA_PBS_TARGET_UUID "\x79\x61\x35\xf0\xf0\xc5\x11\xd8\x09\x66\x08\x00\x20\x0c\x9a\x66"
+#define BTA_PBS_UUID_LENGTH 16
+#define BTA_PBS_MAX_AUTH_KEY_SIZE 16 /* Must not be greater than OBX_MAX_AUTH_KEY_SIZE */
+
+#define BTA_PBS_DEFAULT_VERSION 0x0101 /* for PBAP PSE version 1.1 */
+
+
+/* Configuration structure */
+typedef struct
+{
+ UINT8 realm_charset; /* Server only */
+ BOOLEAN userid_req; /* TRUE if user id is required during obex authentication (Server only) */
+ UINT8 supported_features; /* Server supported features */
+ UINT8 supported_repositories; /* Server supported repositories */
+
+} tBTA_PBS_CFG;
+
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+
+#endif /* BTA_PBS_INT_H */
diff --git a/bta/sys/bd.c b/bta/sys/bd.c
new file mode 100644
index 0000000..052f9b9
--- /dev/null
+++ b/bta/sys/bd.c
@@ -0,0 +1,112 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * BD address services.
+ *
+ ******************************************************************************/
+
+#include "data_types.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/* global constant for "any" bd addr */
+const BD_ADDR bd_addr_any = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+const BD_ADDR bd_addr_null= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/*****************************************************************************
+** Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bdcpy
+**
+** Description Copy bd addr b to a.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bdcpy(BD_ADDR a, const BD_ADDR b)
+{
+ int i;
+
+ for (i = BD_ADDR_LEN; i != 0; i--)
+ {
+ *a++ = *b++;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bdcmp
+**
+** Description Compare bd addr b to a.
+**
+**
+** Returns Zero if b==a, nonzero otherwise (like memcmp).
+**
+*******************************************************************************/
+int bdcmp(const BD_ADDR a, const BD_ADDR b)
+{
+ int i;
+
+ for (i = BD_ADDR_LEN; i != 0; i--)
+ {
+ if (*a++ != *b++)
+ {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function bdcmpany
+**
+** Description Compare bd addr to "any" bd addr.
+**
+**
+** Returns Zero if a equals bd_addr_any.
+**
+*******************************************************************************/
+int bdcmpany(const BD_ADDR a)
+{
+ return bdcmp(a, bd_addr_any);
+}
+
+/*******************************************************************************
+**
+** Function bdsetany
+**
+** Description Set bd addr to "any" bd addr.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bdsetany(BD_ADDR a)
+{
+ bdcpy(a, bd_addr_any);
+}
diff --git a/bta/sys/bta_sys.h b/bta/sys/bta_sys.h
new file mode 100644
index 0000000..5d724e5
--- /dev/null
+++ b/bta/sys/bta_sys.h
@@ -0,0 +1,308 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the public interface file for the BTA system manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_H
+#define BTA_SYS_H
+
+#include "bt_target.h"
+#include "gki.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* event handler function type */
+typedef BOOLEAN (tBTA_SYS_EVT_HDLR)(BT_HDR *p_msg);
+
+/* disable function type */
+typedef void (tBTA_SYS_DISABLE)(void);
+
+
+/* HW modules */
+enum
+{
+ BTA_SYS_HW_BLUETOOTH,
+ BTA_SYS_HW_FMRX,
+ BTA_SYS_HW_FMTX,
+ BTA_SYS_HW_GPS,
+ BTA_SYS_HW_SENSOR,
+ BTA_SYS_HW_NFC,
+ BTA_SYS_HW_RT,
+
+ BTA_SYS_MAX_HW_MODULES
+};
+
+typedef UINT16 tBTA_SYS_HW_MODULE;
+
+#ifndef BTA_DM_NUM_JV_ID
+#define BTA_DM_NUM_JV_ID 2
+#endif
+
+/* SW sub-systems */
+#define BTA_ID_SYS 0 /* system manager */
+/* BLUETOOTH PART - from 0 to BTA_ID_BLUETOOTH_MAX */
+#define BTA_ID_DM 1 /* device manager */
+#define BTA_ID_DM_SEARCH 2 /* device manager search */
+#define BTA_ID_DM_SEC 3 /* device manager security */
+#define BTA_ID_DG 4 /* data gateway */
+#define BTA_ID_AG 5 /* audio gateway */
+#define BTA_ID_OPC 6 /* object push client */
+#define BTA_ID_OPS 7 /* object push server */
+#define BTA_ID_FTS 8 /* file transfer server */
+#define BTA_ID_CT 9 /* cordless telephony terminal */
+#define BTA_ID_FTC 10 /* file transfer client */
+#define BTA_ID_SS 11 /* synchronization server */
+#define BTA_ID_PR 12 /* Printer client */
+#define BTA_ID_BIC 13 /* Basic Imaging Client */
+#define BTA_ID_PAN 14 /* Personal Area Networking */
+#define BTA_ID_BIS 15 /* Basic Imaging Server */
+#define BTA_ID_ACC 16 /* Advanced Camera Client */
+#define BTA_ID_SC 17 /* SIM Card Access server */
+#define BTA_ID_AV 18 /* Advanced audio/video */
+#define BTA_ID_AVK 19 /* Audio/video sink */
+#define BTA_ID_HD 20 /* HID Device */
+#define BTA_ID_CG 21 /* Cordless Gateway */
+#define BTA_ID_BP 22 /* Basic Printing Client */
+#define BTA_ID_HH 23 /* Human Interface Device Host */
+#define BTA_ID_PBS 24 /* Phone Book Access Server */
+#define BTA_ID_PBC 25 /* Phone Book Access Client */
+#define BTA_ID_JV 26 /* Java */
+#define BTA_ID_HS 27 /* Headset */
+#define BTA_ID_MSE 28 /* Message Server Equipment */
+#define BTA_ID_MCE 29 /* Message Client Equipment */
+#define BTA_ID_HL 30 /* Health Device Profile*/
+#define BTA_ID_GATTC 31 /* GATT Client */
+#define BTA_ID_GATTS 32 /* GATT Client */
+#define BTA_ID_BLUETOOTH_MAX 33 /* last BT profile */
+
+/* FM */
+#define BTA_ID_FM 34 /* FM */
+#define BTA_ID_FMTX 35 /* FM TX */
+
+/* SENSOR */
+#define BTA_ID_SSR 36 /* Sensor */
+
+/* GPS */
+#define BTA_ID_GPS 37 /* GPS */
+
+/* GENERIC */
+#define BTA_ID_PRM 38
+#define BTA_ID_SYSTEM 39 /* platform-specific */
+#define BTA_ID_SWRAP 40 /* Insight script wrapper */
+#define BTA_ID_MIP 41 /* Multicase Individual Polling */
+#define BTA_ID_RT 42 /* Audio Routing module: This module is always on. */
+
+
+/* JV */
+#define BTA_ID_JV1 43 /* JV1 */
+#define BTA_ID_JV2 44 /* JV2 */
+
+#define BTA_ID_MAX (43 + BTA_DM_NUM_JV_ID)
+
+typedef UINT8 tBTA_SYS_ID;
+
+
+#define BTA_SYS_CONN_OPEN 0x00
+#define BTA_SYS_CONN_CLOSE 0x01
+#define BTA_SYS_APP_OPEN 0x02
+#define BTA_SYS_APP_CLOSE 0x03
+#define BTA_SYS_SCO_OPEN 0x04
+#define BTA_SYS_SCO_CLOSE 0x05
+#define BTA_SYS_CONN_IDLE 0x06
+#define BTA_SYS_CONN_BUSY 0x07
+
+/* for link policy */
+#define BTA_SYS_PLCY_SET 0x10 /* set the link policy to the given addr */
+#define BTA_SYS_PLCY_CLR 0x11 /* clear the link policy to the given addr */
+#define BTA_SYS_PLCY_DEF_SET 0x12 /* set the default link policy */
+#define BTA_SYS_PLCY_DEF_CLR 0x13 /* clear the default link policy */
+#define BTA_SYS_ROLE_CHANGE 0x14 /* role change */
+
+typedef UINT8 tBTA_SYS_CONN_STATUS;
+
+/* Bitmask of sys features */
+#define BTA_SYS_FEAT_PCM2 0x0001
+#define BTA_SYS_FEAT_PCM2_MASTER 0x0002
+
+/* tBTA_PREF_ROLES */
+typedef UINT8 tBTA_SYS_PREF_ROLES;
+
+/* conn callback for role / low power manager*/
+typedef void (tBTA_SYS_CONN_CBACK)(tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+/* conn callback for role / low power manager*/
+typedef void (tBTA_SYS_SSR_CFG_CBACK)(UINT8 id, UINT8 app_id, UINT16 latency, UINT16 tout);
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+/* eir callback for adding/removeing UUID */
+typedef void (tBTA_SYS_EIR_CBACK)(UINT16 uuid16, BOOLEAN adding);
+#endif
+
+/* registration structure */
+typedef struct
+{
+ tBTA_SYS_EVT_HDLR *evt_hdlr;
+ tBTA_SYS_DISABLE *disable;
+} tBTA_SYS_REG;
+
+/* system manager configuration structure */
+typedef struct
+{
+ UINT16 mbox_evt; /* GKI mailbox event */
+ UINT8 mbox; /* GKI mailbox id */
+ UINT8 timer; /* GKI timer id */
+ UINT8 trace_level; /* initial trace level */
+} tBTA_SYS_CFG;
+
+/* data type to send events to BTA SYS HW manager */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_SYS_HW_MODULE hw_module;
+} tBTA_SYS_HW_MSG;
+
+
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* trace level */
+extern UINT8 appl_trace_level;
+
+/*****************************************************************************
+** Macros
+*****************************************************************************/
+
+/* Calculate start of event enumeration; id is top 8 bits of event */
+#define BTA_SYS_EVT_START(id) ((id) << 8)
+
+/*****************************************************************************
+** events for BTA SYS HW manager
+*****************************************************************************/
+
+/* events sent to SYS HW manager - must be kept synchronized with tables in bta_sys_main.c */
+enum
+{
+ /* device manager local device API events */
+ BTA_SYS_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_SYS),
+ BTA_SYS_EVT_ENABLED_EVT,
+ BTA_SYS_EVT_STACK_ENABLED_EVT,
+ BTA_SYS_API_DISABLE_EVT,
+ BTA_SYS_EVT_DISABLED_EVT,
+ BTA_SYS_ERROR_EVT,
+
+ BTA_SYS_MAX_EVT
+};
+
+
+
+/* SYS HW status events - returned by SYS HW manager to other modules. */
+enum
+{
+ BTA_SYS_HW_OFF_EVT,
+ BTA_SYS_HW_ON_EVT,
+ BTA_SYS_HW_STARTING_EVT,
+ BTA_SYS_HW_STOPPING_EVT,
+ BTA_SYS_HW_ERROR_EVT
+
+};
+typedef UINT8 tBTA_SYS_HW_EVT;
+
+/* HW enable callback type */
+typedef void (tBTA_SYS_HW_CBACK)(tBTA_SYS_HW_EVT status);
+
+/*****************************************************************************
+** Function declarations
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+BTA_API extern void bta_sys_init(void);
+BTA_API extern void bta_sys_event(BT_HDR *p_msg);
+BTA_API extern void bta_sys_timer_update(void);
+BTA_API extern void bta_sys_disable_timers(void);
+BTA_API extern void bta_sys_set_trace_level(UINT8 level);
+extern void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg);
+extern void bta_sys_deregister(UINT8 id);
+extern BOOLEAN bta_sys_is_register(UINT8 id);
+extern UINT16 bta_sys_get_sys_features(void);
+extern void bta_sys_sendmsg(void *p_msg);
+extern void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout);
+extern void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle);
+extern void bta_sys_disable(tBTA_SYS_HW_MODULE module);
+
+extern void bta_sys_hw_register( tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK *cback);
+extern void bta_sys_hw_unregister( tBTA_SYS_HW_MODULE module );
+
+
+extern void bta_sys_rm_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_pm_register(tBTA_SYS_CONN_CBACK * p_cback);
+
+extern void bta_sys_policy_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_sco_register(tBTA_SYS_CONN_CBACK * p_cback);
+
+
+extern void bta_sys_conn_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_conn_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_app_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_app_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_use(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_unuse(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_idle(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_busy(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+#if (BTM_SSR_INCLUDED == TRUE)
+extern void bta_sys_ssr_cfg_register(tBTA_SYS_SSR_CFG_CBACK * p_cback);
+extern void bta_sys_chg_ssr_config (UINT8 id, UINT8 app_id, UINT16 max_latency, UINT16 min_tout);
+#endif
+
+extern void bta_sys_role_chg_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_notify_role_chg(BD_ADDR_PTR p_bda, UINT8 new_role, UINT8 hci_status);
+extern void bta_sys_collision_register(UINT8 bta_id, tBTA_SYS_CONN_CBACK *p_cback);
+extern void bta_sys_notify_collision (BD_ADDR_PTR p_bda);
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+extern void bta_sys_eir_register(tBTA_SYS_EIR_CBACK * p_cback);
+extern void bta_sys_add_uuid(UINT16 uuid16);
+extern void bta_sys_remove_uuid(UINT16 uuid16);
+#else
+#define bta_sys_eir_register(ut)
+#define bta_sys_add_uuid(ut)
+#define bta_sys_remove_uuid(ut)
+#endif
+
+extern void bta_sys_set_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr);
+extern void bta_sys_clear_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr);
+extern void bta_sys_set_default_policy (UINT8 id, UINT8 policy);
+extern void bta_sys_clear_default_policy (UINT8 id, UINT8 policy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_SYS_H */
diff --git a/bta/sys/bta_sys_cfg.c b/bta/sys/bta_sys_cfg.c
new file mode 100644
index 0000000..bcc7e40
--- /dev/null
+++ b/bta/sys/bta_sys_cfg.c
@@ -0,0 +1,55 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains compile-time configurable constants for the BTA
+ * system manager.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "gki.h"
+#include "bta_sys.h"
+
+/* GKI task mailbox event for BTA. */
+#ifndef BTA_MBOX_EVT
+#define BTA_MBOX_EVT TASK_MBOX_2_EVT_MASK
+#endif
+
+/* GKI task mailbox for BTA. */
+#ifndef BTA_MBOX
+#define BTA_MBOX TASK_MBOX_2
+#endif
+
+/* GKI timer id used for protocol timer for BTA. */
+#ifndef BTA_TIMER
+#define BTA_TIMER TIMER_1
+#endif
+
+const tBTA_SYS_CFG bta_sys_cfg =
+{
+ BTA_MBOX_EVT, /* GKI mailbox event */
+ BTA_MBOX, /* GKI mailbox id */
+ BTA_TIMER, /* GKI timer id */
+ APPL_INITIAL_TRACE_LEVEL /* initial trace level */
+};
+
+tBTA_SYS_CFG *p_bta_sys_cfg = (tBTA_SYS_CFG *)&bta_sys_cfg;
+
+
diff --git a/bta/sys/bta_sys_ci.c b/bta/sys/bta_sys_ci.c
new file mode 100644
index 0000000..d191077
--- /dev/null
+++ b/bta/sys/bta_sys_ci.c
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2010-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation file for BTA system call-in functions.
+ *
+ ******************************************************************************/
+
+#include "bta_sys.h"
+#include "bta_sys_ci.h"
+
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_ci_enabled
+**
+** Description This function must be called in response to function
+** bta_sys_hw_enable_co(), when HW is indeed enabled
+**
+**
+** Returns void
+**
+*******************************************************************************/
+ void bta_sys_hw_ci_enabled(tBTA_SYS_HW_MODULE module )
+
+{
+ tBTA_SYS_HW_MSG *p_msg;
+
+ if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_SYS_EVT_ENABLED_EVT;
+ p_msg->hw_module = module;
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_ci_disabled
+**
+** Description This function must be called in response to function
+** bta_sys_hw_disable_co() when HW is really OFF
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_hw_ci_disabled( tBTA_SYS_HW_MODULE module )
+{
+ tBTA_SYS_HW_MSG *p_msg;
+
+ if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+ {
+ p_msg->hdr.event = BTA_SYS_EVT_DISABLED_EVT;
+ p_msg->hw_module = module;
+
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
diff --git a/bta/sys/bta_sys_conn.c b/bta/sys/bta_sys_conn.c
new file mode 100644
index 0000000..b495085
--- /dev/null
+++ b/bta/sys/bta_sys_conn.c
@@ -0,0 +1,577 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Routes connection status callbacks from various sub systems to DM
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_sys_int.h"
+#include "gki.h"
+
+
+/*******************************************************************************
+**
+** Function bta_sys_rm_register
+**
+** Description Called by BTA DM to register role management callbacks
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_rm_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+ bta_sys_cb.prm_cb = p_cback;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_sys_policy_register
+**
+** Description Called by BTA DM to register link policy change callbacks
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_policy_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+ bta_sys_cb.p_policy_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_role_chg_register
+**
+** Description Called by BTA AV to register role change callbacks
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_role_chg_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+ bta_sys_cb.p_role_cb = p_cback;
+}
+/*******************************************************************************
+**
+** Function bta_sys_ssr_cfg_register
+**
+** Description Called by BTA DM to register SSR configuration callback
+**
+**
+** Returns void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+void bta_sys_ssr_cfg_register(tBTA_SYS_SSR_CFG_CBACK * p_cback)
+{
+ bta_sys_cb.p_ssr_cb = p_cback;
+}
+#endif
+/*******************************************************************************
+**
+** Function bta_sys_role_chg_register
+**
+** Description Called by BTA AV to register role change callbacks
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_notify_role_chg(BD_ADDR_PTR p_bda, UINT8 new_role, UINT8 hci_status)
+{
+ if (bta_sys_cb.p_role_cb)
+ {
+ bta_sys_cb.p_role_cb(BTA_SYS_ROLE_CHANGE, new_role, hci_status, p_bda);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_collision_register
+**
+** Description Called by any BTA module to register for collision event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_collision_register(UINT8 bta_id, tBTA_SYS_CONN_CBACK *p_cback)
+{
+ UINT8 index;
+
+ for (index = 0; index < MAX_COLLISION_REG; index++)
+ {
+ if ((bta_sys_cb.colli_reg.id[index] == bta_id) ||
+ (bta_sys_cb.colli_reg.id[index] == 0))
+ {
+ bta_sys_cb.colli_reg.id[index] = bta_id;
+ bta_sys_cb.colli_reg.p_coll_cback[index] = p_cback;
+ return;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_notify_collision
+**
+** Description Called by BTA DM to notify collision event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_notify_collision (BD_ADDR_PTR p_bda)
+{
+ UINT8 index;
+
+ for (index = 0; index < MAX_COLLISION_REG; index++)
+ {
+ if ((bta_sys_cb.colli_reg.id[index] != 0) &&
+ (bta_sys_cb.colli_reg.p_coll_cback[index] != NULL))
+ {
+ bta_sys_cb.colli_reg.p_coll_cback[index] (0, BTA_ID_SYS, 0, p_bda);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_sco_register
+**
+** Description Called by BTA AV to register sco connection change callbacks
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_sco_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+ bta_sys_cb.p_sco_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_pm_register
+**
+** Description Called by BTA DM to register power management callbacks
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_pm_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+ bta_sys_cb.ppm_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_conn_open
+**
+** Description Called by BTA subsystems when a connection is made to
+** the service
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_conn_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ if(bta_sys_cb.prm_cb)
+ {
+
+ bta_sys_cb.prm_cb(BTA_SYS_CONN_OPEN, id, app_id, peer_addr);
+
+ }
+
+ if(bta_sys_cb.ppm_cb)
+ {
+
+ bta_sys_cb.ppm_cb(BTA_SYS_CONN_OPEN, id, app_id, peer_addr);
+
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_sys_conn_close
+**
+** Description Called by BTA subsystems when a connection to the service
+** is closed
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_conn_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ if(bta_sys_cb.prm_cb)
+ {
+
+ bta_sys_cb.prm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
+
+ }
+
+ if(bta_sys_cb.ppm_cb)
+ {
+
+ bta_sys_cb.ppm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
+
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_sys_app_open
+**
+** Description Called by BTA subsystems when application initiates connection
+** to a peer device
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_app_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ if(bta_sys_cb.ppm_cb)
+ {
+ bta_sys_cb.ppm_cb(BTA_SYS_APP_OPEN, id, app_id, peer_addr);
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_sys_app_close
+**
+** Description Called by BTA subsystems when application initiates close
+** of connection to peer device
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_app_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ if(bta_sys_cb.ppm_cb)
+ {
+ bta_sys_cb.ppm_cb(BTA_SYS_APP_CLOSE, id, app_id, peer_addr);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_sys_sco_open
+**
+** Description Called by BTA subsystems when sco connection for that service
+** is open
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_sco_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ /* AG triggers p_sco_cb by bta_sys_sco_use. */
+ if((id != BTA_ID_AG) && (bta_sys_cb.p_sco_cb))
+ {
+ /* without querying BTM_GetNumScoLinks() */
+ bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, peer_addr);
+ }
+
+ if(bta_sys_cb.ppm_cb)
+ {
+ bta_sys_cb.ppm_cb(BTA_SYS_SCO_OPEN, id, app_id, peer_addr);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_sco_close
+**
+** Description Called by BTA subsystems when sco connection for that service
+** is closed
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_sco_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ UINT8 num_sco_links;
+
+ if((id != BTA_ID_AG) && (bta_sys_cb.p_sco_cb))
+ {
+ num_sco_links = BTM_GetNumScoLinks();
+ bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, peer_addr);
+ }
+
+ if(bta_sys_cb.ppm_cb)
+ {
+ bta_sys_cb.ppm_cb(BTA_SYS_SCO_CLOSE, id, app_id, peer_addr);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_sco_use
+**
+** Description Called by BTA subsystems when that service needs to use sco.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_sco_use(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ /* AV streaming need to be suspended before SCO is connected. */
+ if(bta_sys_cb.p_sco_cb)
+ {
+ /* without querying BTM_GetNumScoLinks() */
+ bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, peer_addr);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_sco_unuse
+**
+** Description Called by BTA subsystems when sco connection for that service
+** is no longer needed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_sco_unuse(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ UINT8 num_sco_links;
+
+ if((bta_sys_cb.p_sco_cb))
+ {
+ num_sco_links = BTM_GetNumScoLinks();
+ bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, peer_addr);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_sys_chg_ssr_config
+**
+** Description Called by BTA subsystems to indicate that the given app SSR setting
+** need to be changed.
+**
+** Returns void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+void bta_sys_chg_ssr_config (UINT8 id, UINT8 app_id, UINT16 max_latency, UINT16 min_tout)
+{
+ if(bta_sys_cb.p_ssr_cb)
+ {
+ bta_sys_cb.p_ssr_cb(id, app_id, max_latency, min_tout);
+ }
+}
+#endif
+/*******************************************************************************
+**
+** Function bta_sys_set_policy
+**
+** Description Called by BTA subsystems to indicate that the given link
+** policy to peer device should be set
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_set_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr)
+{
+ if(bta_sys_cb.p_policy_cb)
+ {
+ bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_SET, id, policy, peer_addr);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_clear_policy
+**
+** Description Called by BTA subsystems to indicate that the given link
+** policy to peer device should be clear
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_clear_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr)
+{
+ if(bta_sys_cb.p_policy_cb)
+ {
+ bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_CLR, id, policy, peer_addr);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_set_default_policy
+**
+** Description Called by BTA subsystems to indicate that the given default
+** link policy should be set
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_set_default_policy (UINT8 id, UINT8 policy)
+{
+ if(bta_sys_cb.p_policy_cb)
+ {
+ bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_SET, id, policy, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_clear_default_policy
+**
+** Description Called by BTA subsystems to indicate that the given default
+** link policy should be clear
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_clear_default_policy (UINT8 id, UINT8 policy)
+{
+ if(bta_sys_cb.p_policy_cb)
+ {
+ bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_CLR, id, policy, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_idle
+**
+** Description Called by BTA subsystems to indicate that the connection to
+** peer device is idle
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_idle(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+
+ if(bta_sys_cb.prm_cb)
+ {
+
+ bta_sys_cb.prm_cb(BTA_SYS_CONN_IDLE, id, app_id, peer_addr);
+
+ }
+
+ if(bta_sys_cb.ppm_cb)
+ {
+
+ bta_sys_cb.ppm_cb(BTA_SYS_CONN_IDLE, id, app_id, peer_addr);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_busy
+**
+** Description Called by BTA subsystems to indicate that the connection to
+** peer device is busy
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_busy(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+ if(bta_sys_cb.prm_cb)
+ {
+
+ bta_sys_cb.prm_cb(BTA_SYS_CONN_BUSY, id, app_id, peer_addr);
+
+ }
+
+ if(bta_sys_cb.ppm_cb)
+ {
+
+ bta_sys_cb.ppm_cb(BTA_SYS_CONN_BUSY, id, app_id, peer_addr);
+
+ }
+}
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+/*******************************************************************************
+**
+** Function bta_sys_eir_register
+**
+** Description Called by BTA DM to register EIR utility function that can be
+** used by the other BTA modules to add/remove UUID.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_eir_register(tBTA_SYS_EIR_CBACK * p_cback)
+{
+ bta_sys_cb.eir_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_add_uuid
+**
+** Description Called by BTA subsystems to indicate to DM that new service
+** class UUID is added.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_add_uuid(UINT16 uuid16)
+{
+ if(bta_sys_cb.eir_cb)
+ {
+ bta_sys_cb.eir_cb(uuid16, TRUE );
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_remove_uuid
+**
+** Description Called by BTA subsystems to indicate to DM that the service
+** class UUID is removed.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_remove_uuid(UINT16 uuid16)
+{
+ if(bta_sys_cb.eir_cb)
+ {
+ bta_sys_cb.eir_cb(uuid16, FALSE);
+ }
+}
+#endif
+
diff --git a/bta/sys/bta_sys_int.h b/bta/sys/bta_sys_int.h
new file mode 100644
index 0000000..d187b29
--- /dev/null
+++ b/bta/sys/bta_sys_int.h
@@ -0,0 +1,119 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the private interface file for the BTA system manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_INT_H
+#define BTA_SYS_INT_H
+
+#include "ptim.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/*****************************************************************************
+** state table
+*****************************************************************************/
+
+/* SYS HW state */
+enum
+{
+ BTA_SYS_HW_OFF,
+ BTA_SYS_HW_STARTING,
+ BTA_SYS_HW_ON,
+ BTA_SYS_HW_STOPPING
+};
+typedef UINT8 tBTA_SYS_HW_STATE;
+
+/* Collision callback */
+#define MAX_COLLISION_REG 5
+
+typedef struct
+{
+ UINT8 id[MAX_COLLISION_REG];
+ tBTA_SYS_CONN_CBACK *p_coll_cback[MAX_COLLISION_REG];
+} tBTA_SYS_COLLISION;
+
+/* system manager control block */
+typedef struct
+{
+ tBTA_SYS_REG *reg[BTA_ID_MAX]; /* registration structures */
+ BOOLEAN is_reg[BTA_ID_MAX]; /* registration structures */
+ tPTIM_CB ptim_cb; /* protocol timer list */
+ BOOLEAN timers_disabled; /* TRUE if sys timers disabled */
+ UINT8 task_id; /* GKI task id */
+ tBTA_SYS_HW_STATE state;
+ tBTA_SYS_HW_CBACK *sys_hw_cback[BTA_SYS_MAX_HW_MODULES]; /* enable callback for each HW modules */
+ UINT32 sys_hw_module_active; /* bitmask of all active modules */
+ UINT16 sys_features; /* Bitmask of sys features */
+
+ tBTA_SYS_CONN_CBACK *prm_cb; /* role management callback registered by DM */
+ tBTA_SYS_CONN_CBACK *ppm_cb; /* low power management callback registered by DM */
+ tBTA_SYS_CONN_CBACK *p_policy_cb; /* link policy change callback registered by DM */
+ tBTA_SYS_CONN_CBACK *p_sco_cb; /* SCO connection change callback registered by AV */
+ tBTA_SYS_CONN_CBACK *p_role_cb; /* role change callback registered by AV */
+ tBTA_SYS_COLLISION colli_reg; /* collision handling module */
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+ tBTA_SYS_EIR_CBACK *eir_cb; /* add/remove UUID into EIR */
+#endif
+#if (BTM_SSR_INCLUDED == TRUE)
+ tBTA_SYS_SSR_CFG_CBACK *p_ssr_cb;
+#endif
+} tBTA_SYS_CB;
+
+
+
+
+/*****************************************************************************
+** Global variables
+*****************************************************************************/
+
+/* system manager control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_SYS_CB bta_sys_cb;
+#else
+extern tBTA_SYS_CB *bta_sys_cb_ptr;
+#define bta_sys_cb (*bta_sys_cb_ptr)
+#endif
+
+
+/* system manager configuration structure */
+extern tBTA_SYS_CFG *p_bta_sys_cfg;
+
+
+
+/* functions used for BTA SYS HW state machine */
+void bta_sys_hw_btm_cback( tBTM_DEV_STATUS status );
+void bta_sys_hw_error(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg );
+void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+
+BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg);
+
+
+
+
+
+#endif /* BTA_SYS_INT_H */
diff --git a/bta/sys/bta_sys_main.c b/bta/sys/bta_sys_main.c
new file mode 100644
index 0000000..c1554bb
--- /dev/null
+++ b/bta/sys/bta_sys_main.c
@@ -0,0 +1,722 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the main implementation file for the BTA system manager.
+ *
+ ******************************************************************************/
+
+#include "btm_api.h"
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_sys_int.h"
+#include "bta_sys_ci.h"
+#include "bta_sys_co.h"
+#if BTA_FM_INCLUDED == TRUE
+#include "bta_fm_api.h"
+#endif
+#if BTA_FMTX_INCLUDED == TRUE
+#include "bta_fmtx_api.h"
+#endif
+#if GPS_INCLUDED == TRUE
+#include "bta_gps_api.h"
+#endif
+
+#include "gki.h"
+#include "ptim.h"
+#include <string.h>
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+
+/* protocol timer update period, in milliseconds */
+#ifndef BTA_SYS_TIMER_PERIOD
+#define BTA_SYS_TIMER_PERIOD 1000
+#endif
+
+/* system manager control block definition */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_SYS_CB bta_sys_cb;
+#endif
+
+/* trace level */
+/* TODO Bluedroid - Hard-coded trace levels - Needs to be configurable */
+UINT8 appl_trace_level = BT_TRACE_LEVEL_DEBUG; //APPL_INITIAL_TRACE_LEVEL;
+UINT8 btif_trace_level = BT_TRACE_LEVEL_DEBUG;
+
+static const tBTA_SYS_REG bta_sys_hw_reg =
+{
+ bta_sys_sm_execute,
+ NULL
+};
+
+
+/* type for action functions */
+typedef void (*tBTA_SYS_ACTION)(tBTA_SYS_HW_MSG *p_data);
+
+/* action function list */
+const tBTA_SYS_ACTION bta_sys_action[] =
+{
+ /* device manager local device API events - cf bta_sys.h for events */
+ bta_sys_hw_api_enable, /* 0 BTA_SYS_HW_API_ENABLE_EVT */
+ bta_sys_hw_evt_enabled, /* 1 BTA_SYS_HW_EVT_ENABLED_EVT */
+ bta_sys_hw_evt_stack_enabled, /* 2 BTA_SYS_HW_EVT_STACK_ENABLED_EVT */
+ bta_sys_hw_api_disable, /* 3 BTA_SYS_HW_API_DISABLE_EVT */
+ bta_sys_hw_evt_disabled, /* 4 BTA_SYS_HW_EVT_DISABLED_EVT */
+ bta_sys_hw_error /* 5 BTA_SYS_HW_ERROR_EVT */
+};
+
+/* state machine action enumeration list */
+enum
+{
+ /* device manager local device API events */
+ BTA_SYS_HW_API_ENABLE,
+ BTA_SYS_HW_EVT_ENABLED,
+ BTA_SYS_HW_EVT_STACK_ENABLED,
+ BTA_SYS_HW_API_DISABLE,
+ BTA_SYS_HW_EVT_DISABLED,
+ BTA_SYS_HW_ERROR
+};
+
+#define BTA_SYS_NUM_ACTIONS (BTA_SYS_MAX_EVT & 0x00ff)
+#define BTA_SYS_IGNORE BTA_SYS_NUM_ACTIONS
+
+/* state table information */
+#define BTA_SYS_ACTIONS 2 /* number of actions */
+#define BTA_SYS_NEXT_STATE 2 /* position of next state */
+#define BTA_SYS_NUM_COLS 3 /* number of columns in state tables */
+
+
+/* state table for OFF state */
+const UINT8 bta_sys_hw_off[][BTA_SYS_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next State */
+/* API_ENABLE */ {BTA_SYS_HW_API_ENABLE, BTA_SYS_IGNORE, BTA_SYS_HW_STARTING},
+/* EVT_ENABLED */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_STARTING},
+/* STACK_ENABLED */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_ON},
+/* API_DISABLE */ {BTA_SYS_HW_EVT_DISABLED, BTA_SYS_IGNORE, BTA_SYS_HW_OFF},
+/* EVT_DISABLED */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_OFF},
+/* EVT_ERROR */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_OFF}
+};
+
+const UINT8 bta_sys_hw_starting[][BTA_SYS_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next State */
+/* API_ENABLE */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_STARTING}, /* wait for completion event */
+/* EVT_ENABLED */ {BTA_SYS_HW_EVT_ENABLED, BTA_SYS_IGNORE, BTA_SYS_HW_STARTING},
+/* STACK_ENABLED */ {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_IGNORE, BTA_SYS_HW_ON},
+/* API_DISABLE */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_STOPPING}, /* successive disable/enable: change state wait for completion to disable */
+/* EVT_DISABLED */ {BTA_SYS_HW_EVT_DISABLED, BTA_SYS_HW_API_ENABLE, BTA_SYS_HW_STARTING}, /* successive enable/disable: notify, then restart HW */
+/* EVT_ERROR */ {BTA_SYS_HW_ERROR, BTA_SYS_IGNORE, BTA_SYS_HW_ON}
+};
+
+const UINT8 bta_sys_hw_on[][BTA_SYS_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next State */
+/* API_ENABLE */ {BTA_SYS_HW_API_ENABLE, BTA_SYS_IGNORE, BTA_SYS_HW_ON},
+/* EVT_ENABLED */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_ON},
+/* STACK_ENABLED */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_ON},
+/* API_DISABLE */ {BTA_SYS_HW_API_DISABLE, BTA_SYS_IGNORE, BTA_SYS_HW_ON}, /* don't change the state here, as some other modules might be active */
+/* EVT_DISABLED */ {BTA_SYS_HW_ERROR, BTA_SYS_IGNORE, BTA_SYS_HW_ON},
+/* EVT_ERROR */ {BTA_SYS_HW_ERROR, BTA_SYS_IGNORE, BTA_SYS_HW_ON}
+};
+
+const UINT8 bta_sys_hw_stopping[][BTA_SYS_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next State */
+/* API_ENABLE */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_STARTING}, /* change state, and wait for completion event to enable */
+/* EVT_ENABLED */ {BTA_SYS_HW_EVT_ENABLED, BTA_SYS_IGNORE, BTA_SYS_HW_STOPPING}, /* successive enable/disable: finish the enable before disabling */
+/* STACK_ENABLED */ {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_HW_API_DISABLE, BTA_SYS_HW_STOPPING}, /* successive enable/disable: notify, then stop */
+/* API_DISABLE */ {BTA_SYS_IGNORE, BTA_SYS_IGNORE, BTA_SYS_HW_STOPPING}, /* wait for completion event */
+/* EVT_DISABLED */ {BTA_SYS_HW_EVT_DISABLED, BTA_SYS_IGNORE, BTA_SYS_HW_OFF},
+/* EVT_ERROR */ {BTA_SYS_HW_API_DISABLE, BTA_SYS_IGNORE, BTA_SYS_HW_STOPPING}
+};
+
+typedef const UINT8 (*tBTA_SYS_ST_TBL)[BTA_SYS_NUM_COLS];
+
+/* state table */
+const tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {
+ bta_sys_hw_off,
+ bta_sys_hw_starting,
+ bta_sys_hw_on,
+ bta_sys_hw_stopping
+};
+
+/*******************************************************************************
+**
+** Function bta_sys_init
+**
+** Description BTA initialization; called from task initialization.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void bta_sys_init(void)
+{
+ memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));
+ ptim_init(&bta_sys_cb.ptim_cb, BTA_SYS_TIMER_PERIOD, p_bta_sys_cfg->timer);
+ bta_sys_cb.task_id = GKI_get_taskid();
+ appl_trace_level = p_bta_sys_cfg->trace_level;
+
+ /* register BTA SYS message handler */
+ bta_sys_register( BTA_ID_SYS, &bta_sys_hw_reg);
+
+ /* register for BTM notifications */
+ BTM_RegisterForDeviceStatusNotif ((tBTM_DEV_STATUS_CB*)&bta_sys_hw_btm_cback );
+
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+ bta_ar_init();
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_sm_execute
+**
+** Description State machine event handling function for DM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg)
+{
+ BOOLEAN freebuf = TRUE;
+ tBTA_SYS_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+ APPL_TRACE_EVENT2("bta_sys_sm_execute state:%d, event:0x%x", bta_sys_cb.state, p_msg->event);
+
+ /* look up the state table for the current state */
+ state_table = bta_sys_st_tbl[bta_sys_cb.state];
+ /* update state */
+ bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_SYS_ACTIONS; i++)
+ {
+ if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE)
+ {
+ (*bta_sys_action[action])( (tBTA_SYS_HW_MSG*) p_msg);
+ }
+ else
+ {
+ break;
+ }
+ }
+ return freebuf;
+
+}
+
+
+void bta_sys_hw_register( tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK *cback)
+{
+ bta_sys_cb.sys_hw_cback[module]=cback;
+}
+
+
+void bta_sys_hw_unregister( tBTA_SYS_HW_MODULE module )
+{
+ bta_sys_cb.sys_hw_cback[module]=NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_btm_cback
+**
+** Description This function is registered by BTA SYS to BTM in order to get status notifications
+**
+**
+** Returns
+**
+*******************************************************************************/
+void bta_sys_hw_btm_cback( tBTM_DEV_STATUS status )
+{
+
+ tBTA_SYS_HW_MSG *sys_event;
+
+ APPL_TRACE_DEBUG1(" bta_sys_hw_btm_cback was called with parameter: %i" , status );
+
+ /* send a message to BTA SYS */
+ if ((sys_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+ {
+ if (status == BTM_DEV_STATUS_UP)
+ sys_event->hdr.event = BTA_SYS_EVT_STACK_ENABLED_EVT;
+ else if (status == BTM_DEV_STATUS_DOWN)
+ sys_event->hdr.event = BTA_SYS_ERROR_EVT;
+ else
+ {
+ /* BTM_DEV_STATUS_CMD_TOUT is ignored for now. */
+ GKI_freebuf (sys_event);
+ sys_event = NULL;
+ }
+
+ if (sys_event)
+ {
+ bta_sys_sendmsg(sys_event);
+ }
+ }
+ else
+ {
+ APPL_TRACE_DEBUG0("ERROR bta_sys_hw_btm_cback couldn't send msg" );
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_error
+**
+** Description In case the HW device stops answering... Try to turn it off, then re-enable all
+** previously active SW modules.
+**
+** Returns success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_error(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+
+ UINT8 module_index;
+
+ APPL_TRACE_DEBUG1("%s", __FUNCTION__);
+
+ for (module_index = 0; module_index < BTA_SYS_MAX_HW_MODULES; module_index++)
+ {
+ if( bta_sys_cb.sys_hw_module_active & ((UINT32)1 << module_index )) {
+ switch( module_index)
+ {
+ case BTA_SYS_HW_BLUETOOTH:
+ /* Send BTA_SYS_HW_ERROR_EVT to DM */
+ if (bta_sys_cb.sys_hw_cback[module_index] != NULL)
+ bta_sys_cb.sys_hw_cback[module_index] (BTA_SYS_HW_ERROR_EVT);
+ break;
+ default:
+ /* not yet supported */
+ break;
+ }
+ }
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_enable
+**
+** Description this function is called after API enable and HW has been turned on
+**
+**
+** Returns success or failure
+**
+*******************************************************************************/
+
+void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg )
+{
+ if ((!bta_sys_cb.sys_hw_module_active) && (bta_sys_cb.state != BTA_SYS_HW_ON))
+ {
+ /* register which HW module was turned on */
+ bta_sys_cb.sys_hw_module_active |= ((UINT32)1 << p_sys_hw_msg->hw_module );
+
+ /* use call-out to power-up HW */
+ bta_sys_hw_co_enable(p_sys_hw_msg->hw_module);
+ }
+ else
+ {
+ /* register which HW module was turned on */
+ bta_sys_cb.sys_hw_module_active |= ((UINT32)1 << p_sys_hw_msg->hw_module );
+
+ /* HW already in use, so directly notify the caller */
+ if (bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )
+ bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]( BTA_SYS_HW_ON_EVT );
+ }
+
+ APPL_TRACE_EVENT2 ("bta_sys_hw_api_enable for %d, active modules 0x%04X",
+ p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_disable
+**
+** Description if no other module is using the HW, this function will call ( if defined ) a user-macro to turn off the HW
+**
+**
+** Returns success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+ APPL_TRACE_DEBUG2("bta_sys_hw_api_disable for %d, active modules: 0x%04X",
+ p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active );
+
+ /* make sure the related SW blocks were stopped */
+ bta_sys_disable( p_sys_hw_msg->hw_module );
+
+
+ /* register which module we turn off */
+ bta_sys_cb.sys_hw_module_active &= ~((UINT32)1 << p_sys_hw_msg->hw_module );
+
+
+ /* if there are still some SW modules using the HW, just provide an answer to the calling */
+ if( bta_sys_cb.sys_hw_module_active != 0 )
+ {
+ /* if there are still some SW modules using the HW, directly notify the caller */
+ if( bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )
+ bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]( BTA_SYS_HW_OFF_EVT );
+ }
+ else
+ {
+ /* manually update the state of our system */
+ bta_sys_cb.state = BTA_SYS_HW_STOPPING;
+ /* and use the call-out to disable HW */
+ bta_sys_hw_co_disable(p_sys_hw_msg->hw_module);
+ }
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_event_enabled
+**
+** Description
+**
+**
+** Returns success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+ APPL_TRACE_EVENT1("bta_sys_hw_evt_enabled for %i", p_sys_hw_msg->hw_module);
+
+#if ( defined BTM_AUTOMATIC_HCI_RESET && BTM_AUTOMATIC_HCI_RESET == TRUE )
+ /* If device is already up, send a fake "BTM DEVICE UP" using BTA SYS state machine */
+ /* If we are in the middle device initialization, BTM_DEVICE_UP will be issued */
+ /* by BTM once initialization is done. */
+ if (BTA_DmIsDeviceUp())
+ {
+ bta_sys_hw_btm_cback (BTM_DEV_STATUS_UP);
+ }
+#else
+
+ /* if HCI reset was not sent during stack start-up */
+ BTM_DeviceReset( NULL );
+
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_event_disabled
+**
+** Description
+**
+**
+** Returns success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+ UINT8 hw_module_index;
+
+ APPL_TRACE_DEBUG1("bta_sys_hw_evt_disabled - module 0x%X", p_sys_hw_msg->hw_module);
+
+ for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++)
+ {
+ if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
+ bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_OFF_EVT);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_event_stack_enabled
+**
+** Description we receive this event from once the SW side is ready ( stack, FW download,... ),
+** i.e. we can really start using the device. So notify the app.
+**
+** Returns success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+ UINT8 hw_module_index;
+
+ APPL_TRACE_DEBUG0(" bta_sys_hw_evt_stack_enabled!notify the callers");
+
+ for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++ )
+ {
+ if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
+ bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_ON_EVT);
+ }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_sys_event
+**
+** Description BTA event handler; called from task event handler.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void bta_sys_event(BT_HDR *p_msg)
+{
+ UINT8 id;
+ BOOLEAN freebuf = TRUE;
+
+ APPL_TRACE_EVENT1("BTA got event 0x%x", p_msg->event);
+
+ /* get subsystem id from event */
+ id = (UINT8) (p_msg->event >> 8);
+
+ /* verify id and call subsystem event handler */
+ if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
+ {
+ freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
+ }
+ else
+ {
+ APPL_TRACE_WARNING1("BTA got unregistered event id %d", id);
+ }
+
+ if (freebuf)
+ {
+ GKI_freebuf(p_msg);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_timer_update
+**
+** Description Update the BTA timer list and handle expired timers.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void bta_sys_timer_update(void)
+{
+ if (!bta_sys_cb.timers_disabled)
+ {
+ ptim_timer_update(&bta_sys_cb.ptim_cb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_register
+**
+** Description Called by other BTA subsystems to register their event
+** handler.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
+{
+ bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
+ bta_sys_cb.is_reg[id] = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_deregister
+**
+** Description Called by other BTA subsystems to de-register
+** handler.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_deregister(UINT8 id)
+{
+ bta_sys_cb.is_reg[id] = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_is_register
+**
+** Description Called by other BTA subsystems to get registeration
+** status.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_sys_is_register(UINT8 id)
+{
+ return bta_sys_cb.is_reg[id];
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_sendmsg
+**
+** Description Send a GKI message to BTA. This function is designed to
+** optimize sending of messages to BTA. It is called by BTA
+** API functions and call-in functions.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_sendmsg(void *p_msg)
+{
+ GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_start_timer
+**
+** Description Start a protocol timer for the specified amount
+** of time in milliseconds.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout)
+{
+ ptim_start_timer(&bta_sys_cb.ptim_cb, p_tle, type, timeout);
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_stop_timer
+**
+** Description Stop a BTA timer.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle)
+{
+ ptim_stop_timer(&bta_sys_cb.ptim_cb, p_tle);
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_disable
+**
+** Description For each registered subsystem execute its disable function.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_disable(tBTA_SYS_HW_MODULE module)
+{
+ int bta_id = 0;
+ int bta_id_max = 0;
+
+ APPL_TRACE_DEBUG1("bta_sys_disable: module %i", module);
+
+ switch( module )
+ {
+ case BTA_SYS_HW_BLUETOOTH:
+ bta_id = BTA_ID_DM;
+ bta_id_max = BTA_ID_BLUETOOTH_MAX;
+ break;
+ case BTA_SYS_HW_FMRX:
+ bta_id = BTA_ID_FM;
+ bta_id_max = BTA_ID_FM;
+ break;
+ case BTA_SYS_HW_FMTX:
+ bta_id = BTA_ID_FMTX;
+ bta_id_max = BTA_ID_FMTX;
+ break;
+ case BTA_SYS_HW_GPS:
+ bta_id = BTA_ID_GPS;
+ bta_id_max = BTA_ID_GPS;
+ break;
+ default:
+ APPL_TRACE_WARNING0("bta_sys_disable: unkown module");
+ return;
+ }
+
+ for ( ; bta_id <= bta_id_max; bta_id++)
+ {
+ if (bta_sys_cb.reg[bta_id] != NULL)
+ {
+ if (bta_sys_cb.is_reg[bta_id] == TRUE && bta_sys_cb.reg[bta_id]->disable != NULL)
+ {
+ (*bta_sys_cb.reg[bta_id]->disable)();
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_disable_timers
+**
+** Description Disable sys timer event handling
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_disable_timers(void)
+{
+ bta_sys_cb.timers_disabled = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_set_trace_level
+**
+** Description Set trace level for BTA
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_set_trace_level(UINT8 level)
+{
+ appl_trace_level = level;
+}
+
+/*******************************************************************************
+**
+** Function bta_sys_get_sys_features
+**
+** Description Returns sys_features to other BTA modules.
+**
+** Returns sys_features
+**
+*******************************************************************************/
+UINT16 bta_sys_get_sys_features (void)
+{
+ return bta_sys_cb.sys_features;
+}
+
+
diff --git a/bta/sys/ptim.c b/bta/sys/ptim.c
new file mode 100644
index 0000000..9dffc66
--- /dev/null
+++ b/bta/sys/ptim.c
@@ -0,0 +1,162 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * Protocol timer services.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "gki.h"
+#include "ptim.h"
+#include "bta_sys.h"
+
+/*******************************************************************************
+**
+** Function ptim_init
+**
+** Description Initialize a protocol timer control block. Parameter
+** period is the GKI timer period in milliseconds. Parameter
+** timer_id is the GKI timer id.
+**
+** Returns void
+**
+*******************************************************************************/
+void ptim_init(tPTIM_CB *p_cb, UINT16 period, UINT8 timer_id)
+{
+ GKI_init_timer_list(&p_cb->timer_queue);
+ p_cb->period = period;
+ p_cb->timer_id = timer_id;
+}
+
+/*******************************************************************************
+**
+** Function ptim_timer_update
+**
+** Description Update the protocol timer list and handle expired timers.
+** This function is called from the task running the protocol
+** timers when the periodic GKI timer expires.
+**
+** Returns void
+**
+*******************************************************************************/
+void ptim_timer_update(tPTIM_CB *p_cb)
+{
+ TIMER_LIST_ENT *p_tle;
+ BT_HDR *p_msg;
+ UINT32 new_ticks_count;
+ INT32 period_in_ticks;
+
+ /* To handle the case when the function is called less frequently than the period
+ we must convert determine the number of ticks since the last update, then
+ convert back to milliseconds before updating timer list */
+ new_ticks_count = GKI_get_tick_count();
+
+ /* Check for wrapped condition */
+ if (new_ticks_count >= p_cb->last_gki_ticks)
+ {
+ period_in_ticks = (INT32)(new_ticks_count - p_cb->last_gki_ticks);
+ }
+ else
+ {
+ period_in_ticks = (INT32)(((UINT32)0xffffffff - p_cb->last_gki_ticks)
+ + new_ticks_count + 1);
+ }
+
+ /* update timer list */
+ GKI_update_timer_list(&p_cb->timer_queue, GKI_TICKS_TO_MS(period_in_ticks));
+
+ p_cb->last_gki_ticks = new_ticks_count;
+
+ /* while there are expired timers */
+ while((p_cb->timer_queue.p_first) && (p_cb->timer_queue.p_first->ticks <= 0))
+ {
+ /* removed expired timer from list */
+ p_tle = p_cb->timer_queue.p_first;
+ GKI_remove_from_timer_list(&p_cb->timer_queue, p_tle);
+
+ /* call timer callback */
+ if(p_tle->p_cback)
+ {
+ (*p_tle->p_cback)(p_tle);
+ }
+ else if(p_tle->event)
+ {
+ if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_msg->event = p_tle->event;
+ p_msg->layer_specific = 0;
+ bta_sys_sendmsg(p_msg);
+ }
+ }
+ }
+
+ /* if timer list is empty stop periodic GKI timer */
+ if (p_cb->timer_queue.p_first == NULL)
+ {
+ GKI_stop_timer(p_cb->timer_id);
+ }
+}
+
+/*******************************************************************************
+**
+** Function ptim_start_timer
+**
+** Description Start a protocol timer for the specified amount
+** of time in seconds.
+**
+** Returns void
+**
+*******************************************************************************/
+void ptim_start_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout)
+{
+ /* if timer list is currently empty, start periodic GKI timer */
+ if (p_cb->timer_queue.p_first == NULL)
+ {
+ p_cb->last_gki_ticks = GKI_get_tick_count();
+ GKI_start_timer(p_cb->timer_id, GKI_MS_TO_TICKS(p_cb->period), TRUE);
+ }
+
+ GKI_remove_from_timer_list(&p_cb->timer_queue, p_tle);
+
+ p_tle->event = type;
+ p_tle->ticks = timeout;
+
+ GKI_add_to_timer_list(&p_cb->timer_queue, p_tle);
+}
+
+/*******************************************************************************
+**
+** Function ptim_stop_timer
+**
+** Description Stop a protocol timer.
+**
+** Returns void
+**
+*******************************************************************************/
+void ptim_stop_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle)
+{
+ GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle);
+
+ /* if timer list is empty stop periodic GKI timer */
+ if (p_cb->timer_queue.p_first == NULL)
+ {
+ GKI_stop_timer(p_cb->timer_id);
+ }
+}
diff --git a/bta/sys/utl.c b/bta/sys/utl.c
new file mode 100644
index 0000000..4bb1d95
--- /dev/null
+++ b/bta/sys/utl.c
@@ -0,0 +1,296 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2003-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This file contains utility functions.
+ *
+ ******************************************************************************/
+#include "utl.h"
+#include "gki.h"
+#include "btm_api.h"
+
+/*******************************************************************************
+**
+** Function utl_str2int
+**
+** Description This utility function converts a character string to an
+** integer. Acceptable values in string are 0-9. If invalid
+** string or string value too large, -1 is returned. Leading
+** spaces are skipped.
+**
+**
+** Returns Integer value or -1 on error.
+**
+*******************************************************************************/
+INT16 utl_str2int(const char *p_s)
+{
+ INT32 val = 0;
+
+ for (;*p_s == ' ' && *p_s != 0; p_s++);
+
+ if (*p_s == 0) return -1;
+
+ for (;;)
+ {
+ if ((*p_s < '0') || (*p_s > '9')) return -1;
+
+ val += (INT32) (*p_s++ - '0');
+
+ if (val > 32767) return -1;
+
+ if (*p_s == 0)
+ {
+ return (INT16) val;
+ }
+ else
+ {
+ val *= 10;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function utl_strucmp
+**
+** Description This utility function compares two strings in uppercase.
+** String p_s must be uppercase. String p_t is converted to
+** uppercase if lowercase. If p_s ends first, the substring
+** match is counted as a match.
+**
+**
+** Returns 0 if strings match, nonzero otherwise.
+**
+*******************************************************************************/
+int utl_strucmp(const char *p_s, const char *p_t)
+{
+ char c;
+
+ while (*p_s && *p_t)
+ {
+ c = *p_t++;
+ if (c >= 'a' && c <= 'z')
+ {
+ c -= 0x20;
+ }
+ if (*p_s++ != c)
+ {
+ return -1;
+ }
+ }
+ /* if p_t hit null first, no match */
+ if (*p_t == 0 && *p_s != 0)
+ {
+ return 1;
+ }
+ /* else p_s hit null first, count as match */
+ else
+ {
+ return 0;
+ }
+}
+
+/*******************************************************************************
+**
+** Function utl_itoa
+**
+** Description This utility function converts a UINT16 to a string. The
+** string is NULL-terminated. The length of the string is
+** returned;
+**
+**
+** Returns Length of string.
+**
+*******************************************************************************/
+UINT8 utl_itoa(UINT16 i, char *p_s)
+{
+ UINT16 j, k;
+ char *p = p_s;
+ BOOLEAN fill = FALSE;
+
+ if (i == 0)
+ {
+ /* take care of zero case */
+ *p++ = '0';
+ }
+ else
+ {
+ for(j = 10000; j > 0; j /= 10)
+ {
+ k = i / j;
+ i %= j;
+ if (k > 0 || fill)
+ {
+ *p++ = k + '0';
+ fill = TRUE;
+ }
+ }
+ }
+ *p = 0;
+ return (UINT8) (p - p_s);
+}
+
+/*******************************************************************************
+**
+** Function utl_freebuf
+**
+** Description This function calls GKI_freebuf to free the buffer passed
+** in, if buffer pointer is not NULL, and also initializes
+** buffer pointer to NULL.
+**
+**
+** Returns Nothing.
+**
+*******************************************************************************/
+void utl_freebuf(void **p)
+{
+ if (*p != NULL)
+ {
+ GKI_freebuf(*p);
+ *p = NULL;
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function utl_set_device_class
+**
+** Description This function updates the local Device Class.
+**
+** Parameters:
+** p_cod - Pointer to the device class to set to
+**
+** cmd - the fields of the device class to update.
+** BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+** BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in the input
+** BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in the input
+** BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class
+** BTA_UTL_INIT_COD - overwrite major, minor, and service class
+**
+** Returns TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_set_device_class(tBTA_UTL_COD *p_cod, UINT8 cmd)
+{
+ UINT8 *dev;
+ UINT16 service;
+ UINT8 minor, major;
+ DEV_CLASS dev_class;
+
+ dev = BTM_ReadDeviceClass();
+ BTM_COD_SERVICE_CLASS( service, dev );
+ BTM_COD_MINOR_CLASS(minor, dev );
+ BTM_COD_MAJOR_CLASS(major, dev );
+
+ switch(cmd)
+ {
+ case BTA_UTL_SET_COD_MAJOR_MINOR:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ break;
+
+ case BTA_UTL_SET_COD_SERVICE_CLASS:
+ /* clear out the bits that is not SERVICE_CLASS bits */
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service | p_cod->service;
+ break;
+
+ case BTA_UTL_CLR_COD_SERVICE_CLASS:
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service & (~p_cod->service);
+ break;
+
+ case BTA_UTL_SET_COD_ALL:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+ service = service | p_cod->service;
+ break;
+
+ case BTA_UTL_INIT_COD:
+ minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+ major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+ service = p_cod->service & BTM_COD_SERVICE_CLASS_MASK;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ /* convert the fields into the device class type */
+ FIELDS_TO_COD(dev_class, minor, major, service);
+
+ if (BTM_SetDeviceClass(dev_class) == BTM_SUCCESS)
+ return TRUE;
+
+ return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function utl_isintstr
+**
+** Description This utility function checks if the given string is an
+** integer string or not
+**
+**
+** Returns TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_isintstr(const char *p_s)
+{
+ UINT16 i = 0;
+
+ for(i=0; p_s[i] != 0; i++)
+ {
+ if(((p_s[i] < '0') || (p_s[i] > '9')) && (p_s[i] != ';'))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function utl_isdialstr
+**
+** Description This utility function checks if the given string contains
+** only dial digits or not
+**
+**
+** Returns TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_isdialstr(const char *p_s)
+{
+ UINT16 i = 0;
+
+ for(i=0; p_s[i] != 0; i++)
+ {
+ if(!(((p_s[i] >= '0') && (p_s[i] <= '9'))
+ || (p_s[i] == '*') || (p_s[i] == '+') || (p_s[i] == '#') || (p_s[i] == ';')
+ || ((p_s[i] >= 'A') && (p_s[i] <= 'C'))))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+