summaryrefslogtreecommitdiffstats
path: root/bta
diff options
context:
space:
mode:
authorAndre Eisenbach <andre@broadcom.com>2012-02-22 13:18:21 -0800
committerMatthew Xie <mattx@google.com>2012-07-14 11:19:11 -0700
commite448862a47c08eb23185aaed574b39264f5005fc (patch)
tree2bc6246e3091315e77224fd798ea2fe8074ef972 /bta
parenta2ca4b83ab8bbbfd8d5f6693e927ed4b82094624 (diff)
downloadexternal_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.zip
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.gz
external_bluetooth_bluedroid-e448862a47c08eb23185aaed574b39264f5005fc.tar.bz2
Initial Bluedroid stack commit
Diffstat (limited to 'bta')
-rw-r--r--bta/Android.mk140
-rw-r--r--bta/ag/bta_ag_act.c848
-rw-r--r--bta/ag/bta_ag_api.c310
-rw-r--r--bta/ag/bta_ag_at.c230
-rw-r--r--bta/ag/bta_ag_at.h108
-rw-r--r--bta/ag/bta_ag_cfg.c51
-rw-r--r--bta/ag/bta_ag_ci.c86
-rw-r--r--bta/ag/bta_ag_cmd.c1789
-rw-r--r--bta/ag/bta_ag_int.h407
-rw-r--r--bta/ag/bta_ag_main.c1000
-rw-r--r--bta/ag/bta_ag_rfc.c428
-rw-r--r--bta/ag/bta_ag_sco.c1650
-rw-r--r--bta/ag/bta_ag_sdp.c491
-rw-r--r--bta/av/bta_av_aact.c2688
-rw-r--r--bta/av/bta_av_act.c2000
-rw-r--r--bta/av/bta_av_api.c568
-rw-r--r--bta/av/bta_av_cfg.c276
-rw-r--r--bta/av/bta_av_ci.c85
-rw-r--r--bta/av/bta_av_int.h706
-rw-r--r--bta/av/bta_av_main.c1318
-rw-r--r--bta/av/bta_av_ssm.c587
-rw-r--r--bta/dg/bta_dg_act.c900
-rw-r--r--bta/dg/bta_dg_api.c218
-rw-r--r--bta/dg/bta_dg_cfg.c54
-rw-r--r--bta/dg/bta_dg_ci.c159
-rw-r--r--bta/dg/bta_dg_int.h220
-rw-r--r--bta/dg/bta_dg_main.c597
-rw-r--r--bta/dm/bta_dm_act.c4678
-rw-r--r--bta/dm/bta_dm_api.c1602
-rw-r--r--bta/dm/bta_dm_cfg.c424
-rw-r--r--bta/dm/bta_dm_ci.c106
-rw-r--r--bta/dm/bta_dm_int.h956
-rw-r--r--bta/dm/bta_dm_main.c331
-rw-r--r--bta/dm/bta_dm_pm.c980
-rw-r--r--bta/dm/bta_dm_sco.c684
-rw-r--r--bta/fs/bta_fs_cfg.c38
-rw-r--r--bta/fs/bta_fs_ci.c268
-rw-r--r--bta/ft/bta_ft_cfg.c86
-rw-r--r--bta/ft/bta_ftc_act.c2062
-rw-r--r--bta/ft/bta_ftc_api.c796
-rw-r--r--bta/ft/bta_ftc_int.h504
-rw-r--r--bta/ft/bta_ftc_main.c689
-rw-r--r--bta/ft/bta_ftc_utils.c608
-rw-r--r--bta/ft/bta_fts_act.c1523
-rw-r--r--bta/ft/bta_fts_api.c230
-rw-r--r--bta/ft/bta_fts_int.h287
-rw-r--r--bta/ft/bta_fts_main.c603
-rw-r--r--bta/ft/bta_fts_sdp.c66
-rw-r--r--bta/ft/bta_fts_utils.c972
-rw-r--r--bta/gatt/bta_gattc_act.c1789
-rw-r--r--bta/gatt/bta_gattc_api.c922
-rw-r--r--bta/gatt/bta_gattc_cache.c1584
-rw-r--r--bta/gatt/bta_gattc_ci.c125
-rw-r--r--bta/gatt/bta_gattc_int.h452
-rw-r--r--bta/gatt/bta_gattc_main.c474
-rw-r--r--bta/gatt/bta_gattc_utils.c652
-rw-r--r--bta/gatt/bta_gatts_act.c785
-rw-r--r--bta/gatt/bta_gatts_api.c500
-rw-r--r--bta/gatt/bta_gatts_int.h233
-rw-r--r--bta/gatt/bta_gatts_main.c122
-rw-r--r--bta/gatt/bta_gatts_utils.c223
-rw-r--r--bta/hd/bta_hd_act.c646
-rw-r--r--bta/hd/bta_hd_api.c236
-rw-r--r--bta/hd/bta_hd_cfg.c151
-rw-r--r--bta/hd/bta_hd_int.h166
-rw-r--r--bta/hd/bta_hd_main.c242
-rw-r--r--bta/hh/bta_hh_act.c1160
-rw-r--r--bta/hh/bta_hh_api.c412
-rw-r--r--bta/hh/bta_hh_cfg.c52
-rw-r--r--bta/hh/bta_hh_int.h235
-rw-r--r--bta/hh/bta_hh_main.c429
-rw-r--r--bta/hh/bta_hh_utils.c409
-rw-r--r--bta/hl/bta_hl_act.c2794
-rw-r--r--bta/hl/bta_hl_api.c472
-rw-r--r--bta/hl/bta_hl_ci.c158
-rw-r--r--bta/hl/bta_hl_int.h845
-rw-r--r--bta/hl/bta_hl_main.c1907
-rw-r--r--bta/hl/bta_hl_sdp.c429
-rw-r--r--bta/hl/bta_hl_utils.c3324
-rw-r--r--bta/include/bd.h89
-rw-r--r--bta/include/bta_ag_api.h496
-rw-r--r--bta/include/bta_ag_ci.h70
-rw-r--r--bta/include/bta_ag_co.h100
-rw-r--r--bta/include/bta_api.h1712
-rw-r--r--bta/include/bta_av_api.h753
-rw-r--r--bta/include/bta_av_ci.h62
-rw-r--r--bta/include/bta_av_co.h400
-rw-r--r--bta/include/bta_dg_api.h198
-rw-r--r--bta/include/bta_dg_ci.h107
-rw-r--r--bta/include/bta_dg_co.h198
-rw-r--r--bta/include/bta_dm_ci.h69
-rw-r--r--bta/include/bta_dm_co.h262
-rw-r--r--bta/include/bta_fs_api.h32
-rw-r--r--bta/include/bta_fs_ci.h244
-rw-r--r--bta/include/bta_fs_co.h690
-rw-r--r--bta/include/bta_ft_api.h724
-rw-r--r--bta/include/bta_gatt_api.h1206
-rw-r--r--bta/include/bta_gattc_ci.h108
-rw-r--r--bta/include/bta_gattc_co.h89
-rw-r--r--bta/include/bta_gatts_co.h70
-rw-r--r--bta/include/bta_hd_api.h289
-rw-r--r--bta/include/bta_hh_api.h444
-rw-r--r--bta/include/bta_hh_co.h60
-rw-r--r--bta/include/bta_hl_api.h895
-rw-r--r--bta/include/bta_hl_ci.h112
-rw-r--r--bta/include/bta_hl_co.h219
-rw-r--r--bta/include/bta_ma_api.h691
-rw-r--r--bta/include/bta_ma_co.h91
-rw-r--r--bta/include/bta_ma_def.h479
-rw-r--r--bta/include/bta_mse_api.h470
-rw-r--r--bta/include/bta_mse_ci.h146
-rw-r--r--bta/include/bta_mse_co.h330
-rw-r--r--bta/include/bta_op_api.h621
-rw-r--r--bta/include/bta_pan_api.h187
-rw-r--r--bta/include/bta_pan_ci.h139
-rw-r--r--bta/include/bta_pan_co.h189
-rw-r--r--bta/include/bta_pbs_api.h298
-rw-r--r--bta/include/bta_pbs_ci.h93
-rw-r--r--bta/include/bta_pbs_co.h160
-rw-r--r--bta/include/bta_prm_api.h57
-rw-r--r--bta/include/bta_sc_api.h193
-rw-r--r--bta/include/bta_sc_ci.h111
-rw-r--r--bta/include/bta_sc_co.h153
-rw-r--r--bta/include/bta_sys_ci.h57
-rw-r--r--bta/include/bta_sys_co.h47
-rw-r--r--bta/include/ptim.h86
-rw-r--r--bta/include/utl.h156
-rw-r--r--bta/ma/bta_ma_api.c1203
-rw-r--r--bta/ma/bta_ma_util.c1750
-rw-r--r--bta/ma/bta_ma_util.h93
-rw-r--r--bta/ma/bta_mse_act.c2763
-rw-r--r--bta/ma/bta_mse_api.c437
-rw-r--r--bta/ma/bta_mse_cfg.c31
-rw-r--r--bta/ma/bta_mse_ci.c251
-rw-r--r--bta/ma/bta_mse_int.h835
-rw-r--r--bta/ma/bta_mse_main.c1367
-rw-r--r--bta/ma/bta_mse_sdp.c63
-rw-r--r--bta/ma/bta_mse_utils.c3867
-rw-r--r--bta/op/bta_op_fmt.c804
-rw-r--r--bta/op/bta_op_fmt.h92
-rw-r--r--bta/op/bta_op_vcal.c158
-rw-r--r--bta/op/bta_op_vcard.c310
-rw-r--r--bta/op/bta_op_vnote.c99
-rw-r--r--bta/op/bta_opc_act.c1017
-rw-r--r--bta/op/bta_opc_api.c214
-rw-r--r--bta/op/bta_opc_int.h257
-rw-r--r--bta/op/bta_opc_main.c425
-rw-r--r--bta/op/bta_opc_utils.c322
-rw-r--r--bta/op/bta_ops_act.c793
-rw-r--r--bta/op/bta_ops_api.c153
-rw-r--r--bta/op/bta_ops_int.h198
-rw-r--r--bta/op/bta_ops_main.c412
-rw-r--r--bta/op/bta_ops_utils.c487
-rw-r--r--bta/pan/bta_pan_act.c718
-rw-r--r--bta/pan/bta_pan_api.c202
-rw-r--r--bta/pan/bta_pan_ci.c248
-rw-r--r--bta/pan/bta_pan_int.h200
-rw-r--r--bta/pan/bta_pan_main.c409
-rw-r--r--bta/pb/bta_pbs_act.c1134
-rw-r--r--bta/pb/bta_pbs_api.c222
-rw-r--r--bta/pb/bta_pbs_cfg.c38
-rw-r--r--bta/pb/bta_pbs_ci.c119
-rw-r--r--bta/pb/bta_pbs_int.h305
-rw-r--r--bta/pb/bta_pbs_main.c515
-rw-r--r--bta/pb/bta_pbs_sdp.c113
-rw-r--r--bta/pb/bta_pbs_utils.c734
-rw-r--r--bta/sys/bd.c99
-rw-r--r--bta/sys/bta_sys.h296
-rw-r--r--bta/sys/bta_sys_cfg.c42
-rw-r--r--bta/sys/bta_sys_ci.c65
-rw-r--r--bta/sys/bta_sys_conn.c565
-rw-r--r--bta/sys/bta_sys_int.h107
-rw-r--r--bta/sys/bta_sys_main.c728
-rw-r--r--bta/sys/ptim.c149
-rw-r--r--bta/sys/utl.c283
175 files changed, 98479 insertions, 0 deletions
diff --git a/bta/Android.mk b/bta/Android.mk
new file mode 100644
index 0000000..bbada7e
--- /dev/null
+++ b/bta/Android.mk
@@ -0,0 +1,140 @@
+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
+
+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 \
+ ./op/bta_op_vcal.c \
+ ./op/bta_opc_utils.c \
+ ./op/bta_opc_main.c \
+ ./op/bta_opc_api.c \
+ ./op/bta_opc_act.c \
+ ./op/bta_ops_utils.c \
+ ./op/bta_op_vcard.c \
+ ./op/bta_ops_main.c \
+ ./op/bta_op_vnote.c \
+ ./op/bta_op_fmt.c \
+ ./op/bta_ops_act.c \
+ ./op/bta_ops_api.c \
+ ./ma/bta_mse_ci.c \
+ ./ma/bta_mse_api.c \
+ ./ma/bta_mse_act.c \
+ ./ma/bta_mse_sdp.c \
+ ./ma/bta_ma_util.c \
+ ./ma/bta_ma_api.c \
+ ./ma/bta_mse_utils.c \
+ ./ma/bta_mse_main.c \
+ ./ma/bta_mse_cfg.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 \
+ ./hd/bta_hd_cfg.c \
+ ./hd/bta_hd_api.c \
+ ./hd/bta_hd_main.c \
+ ./hd/bta_hd_act.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 \
+ ./dg/bta_dg_act.c \
+ ./dg/bta_dg_main.c \
+ ./dg/bta_dg_api.c \
+ ./dg/bta_dg_cfg.c \
+ ./dg/bta_dg_ci.c \
+ ./ft/bta_ft_cfg.c \
+ ./ft/bta_ftc_main.c \
+ ./ft/bta_fts_utils.c \
+ ./ft/bta_fts_sdp.c \
+ ./ft/bta_ftc_api.c \
+ ./ft/bta_ftc_act.c \
+ ./ft/bta_fts_act.c \
+ ./ft/bta_fts_api.c \
+ ./ft/bta_fts_main.c \
+ ./ft/bta_ftc_utils.c \
+ ./pb/bta_pbs_act.c \
+ ./pb/bta_pbs_api.c \
+ ./pb/bta_pbs_sdp.c \
+ ./pb/bta_pbs_utils.c \
+ ./pb/bta_pbs_ci.c \
+ ./pb/bta_pbs_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 \
+ ./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
+
+LOCAL_MODULE := libbt-brcm_bta
+LOCAL_MODULE_TAGS := eng
+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 \
+
+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..af7c371
--- /dev/null
+++ b/bta/ag/bta_ag_act.c
@@ -0,0 +1,848 @@
+/*****************************************************************************
+**
+** Name: bta_ag_act.c
+**
+** Description: This file contains action functions for the audio gateway.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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>
+
+/*****************************************************************************
+** 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 *) &reg);
+}
+
+/*******************************************************************************
+**
+** 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)
+{
+ /* 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..d2e38e2
--- /dev/null
+++ b/bta/ag/bta_ag_api.c
@@ -0,0 +1,310 @@
+/*****************************************************************************
+**
+** Name: bta_ag_api.c
+**
+** Description: This is the implementation of the API for the audio gateway
+** (AG) subsystem of BTA, Widcomm's Bluetooth application
+** layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..4d3bcac
--- /dev/null
+++ b/bta/ag/bta_ag_at.c
@@ -0,0 +1,230 @@
+/*****************************************************************************
+**
+** Name: bta_ag_at.c
+**
+** Description: BTA AG AT command interpreter.
+**
+** Copyright (c) 2004-2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..2bdd6ae
--- /dev/null
+++ b/bta/ag/bta_ag_at.h
@@ -0,0 +1,108 @@
+/*****************************************************************************
+**
+** Name: bta_ag_at.h
+**
+** Description: Interface file for BTA AG AT command interpreter.
+**
+** Copyright (c) 2004-2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..4f878a4
--- /dev/null
+++ b/bta/ag/bta_ag_cfg.c
@@ -0,0 +1,51 @@
+/*****************************************************************************
+**
+** Name: bta_ag_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the audio gateway.
+**
+** Copyright (c) 2003-2006, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..bbd1a55
--- /dev/null
+++ b/bta/ag/bta_ag_ci.c
@@ -0,0 +1,86 @@
+/*****************************************************************************
+**
+** Name: bta_ag_ci.c
+**
+** Description: This is the implementation file for audio gateway call-in
+** functions.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..af86e26
--- /dev/null
+++ b/bta/ag/bta_ag_cmd.c
@@ -0,0 +1,1789 @@
+/*****************************************************************************
+**
+** Name: bta_ag_cmd.c
+**
+** Description: This file contains functions for processing AT commands
+** and results.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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 4000
+
+#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_CALLHELD) && (on_demand == FALSE))
+ {
+ if (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 send OK, else don't call callback, send ERROR */
+ if (p_scb->features & BTA_AG_FEAT_VREC)
+ {
+ 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_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);
+ 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';
+ 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, TRUE);
+ 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..d8f681c
--- /dev/null
+++ b/bta/ag/bta_ag_int.h
@@ -0,0 +1,407 @@
+/*****************************************************************************
+**
+** Name: bta_ag_int.h
+**
+** Description: This is the private interface file for the BTA audio
+** gateway.
+**
+** Copyright (c) 2003-2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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 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..df576cc
--- /dev/null
+++ b/bta/ag/bta_ag_main.c
@@ -0,0 +1,1000 @@
+/*****************************************************************************
+**
+** Name: bta_ag_main.c
+**
+** Description: This is the main implementation file for the BTA
+** audio gateway.
+**
+** Copyright (c) 2003-2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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_SVC_CONN_OPEN, BTA_AG_IGNORE, BTA_AG_OPEN_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 *) &reg);
+ }
+}
+
+/*******************************************************************************
+**
+** 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..bccb2cf
--- /dev/null
+++ b/bta/ag/bta_ag_rfc.c
@@ -0,0 +1,428 @@
+/*****************************************************************************
+**
+** Name: bta_ag_rfc.c
+**
+** Description: This file contains the audio gateway functions
+** controlling the RFCOMM connections.
+**
+** Copyright (c) 2004-2008, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..021b96c
--- /dev/null
+++ b/bta/ag/bta_ag_sco.c
@@ -0,0 +1,1650 @@
+/*****************************************************************************
+**
+** Name: bta_ag_sco.c
+**
+** Description: This file contains functions for managing the
+** SCO connection used in AG.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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, &params);
+ /* 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, &params);
+ }
+
+ 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..a8e06cb
--- /dev/null
+++ b/bta/ag/bta_ag_sdp.c
@@ -0,0 +1,491 @@
+/*****************************************************************************
+**
+** Name: bta_ag_sdp.c
+**
+** Description: This file contains the audio gateway functions
+** performing SDP operations.
+**
+** Copyright (c) 2003-2005, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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;
+#if (BTM_WBS_INCLUDED == TRUE )
+ version = HFP_VERSION_1_6;
+#else
+ version = HFP_VERSION_1_5;
+#endif
+ }
+ 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/av/bta_av_aact.c b/bta/av/bta_av_aact.c
new file mode 100644
index 0000000..aa154b3
--- /dev/null
+++ b/bta/av/bta_av_aact.c
@@ -0,0 +1,2688 @@
+/*****************************************************************************
+**
+** Name: bta_av_aact.c
+**
+** Description: This file contains action functions for
+** advanced audio/video stream state machine.
+** these functions are shared by both audio and video streams.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+#if defined(AV_INCLUDED) && (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;
+
+ /* 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;
+
+ /* We need to know all the SEPs on SNK */
+ /* Getcap for all SEPs will follow after Discover */
+ APPL_TRACE_DEBUG0("bta_av_setconfig_rsp: start DISCOVER");
+ bta_av_discover_req(p_scb, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** 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_DEBUG1("role:x%x", 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_ERROR1("bta_av_str_stopped:audio_open_cnt=%d", bta_av_cb.audio_open_cnt);
+ 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
+ {
+ (*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,
+ &timestamp);
+
+ 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_ERROR2("bta_av_start_ok suspending: %d, role:x%x", suspend, p_scb->role);
+ 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 /* AV_INCLUDED */
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
new file mode 100644
index 0000000..472ed21
--- /dev/null
+++ b/bta/av/bta_av_act.c
@@ -0,0 +1,2000 @@
+/*****************************************************************************
+**
+** Name: bta_av_act.c
+**
+** Description: This file contains action functions for
+** advanced audio/video main state machine.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+#if defined(AV_INCLUDED) && (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);
+ }
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ if (opcode == AVRC_OP_BROWSE)
+ {
+ /* set p_pkt to NULL, so avrc would not free the GKI buffer */
+ p_msg->browse.p_browse_pkt = NULL;
+ }
+#endif
+#endif
+ 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 (AVRC_ADV_CTRL_INCLUDED == TRUE && AVCT_BROWSE_INCLUDED == TRUE)
+ /* listen to browsing channel when the connection is open,
+ - if peer initiated AVRCP connection and local device supports browsing channel */
+ if ((p_cb->features & BTA_AV_FEAT_BROWSE) && (p_cb->rcb[i].peer_features == 0))
+ AVRC_OpenBrowse (p_data->rc_conn_chg.handle, AVCT_ACP);
+#endif
+
+ 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);
+
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE && AVCT_BROWSE_INCLUDED == TRUE)
+ /* if local initiated AVRCP connection and both peer and locals device support browsing channel,
+ * open the browsing channel now */
+ if ((p_cb->features & BTA_AV_FEAT_BROWSE) && (rc_open.peer_features & BTA_AV_FEAT_BROWSE) &&
+ ((p_cb->rcb[i].status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT))
+ {
+ AVRC_OpenBrowse (p_data->rc_conn_chg.handle, AVCT_INT);
+ }
+#endif
+}
+
+
+/*******************************************************************************
+**
+** 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)
+{
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ if (p_data->rc_msg.opcode == AVRC_OP_BROWSE)
+ {
+ utl_freebuf ((void **)&p_data->rc_msg.msg.browse.p_browse_pkt);
+ }
+#endif
+#endif
+}
+
+
+
+/*******************************************************************************
+**
+** 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 if (!AVRC_IsValidAvcType(pdu, p_vendor->hdr.ctype) )
+ {
+ APPL_TRACE_DEBUG2("Invalid pdu/ctype: 0x%x, %d", pdu, p_vendor->hdr.ctype);
+ /* reject invalid message without reporting to app */
+ evt = 0;
+ p_rc_rsp->rsp.status = AVRC_STS_BAD_CMD;
+ }
+ 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 (AVRC_METADATA_INCLUDED == TRUE)
+ tAVRC_STS res;
+ UINT8 ctype;
+ tAVRC_RESPONSE rc_rsp;
+
+ rc_rsp.rsp.status = BTA_AV_STS_NO_RSP;
+#endif
+
+ 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;
+#if (AVRC_METADATA_INCLUDED == TRUE)
+ if (p_cb->features & BTA_AV_FEAT_METADATA)
+ p_data->rc_msg.msg.hdr.ctype = bta_av_group_navi_supported(p_data->rc_msg.msg.pass.pass_len, p_data->rc_msg.msg.pass.p_pass_data);
+#endif
+ }
+ 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)
+ {
+#if (AVRC_METADATA_INCLUDED == TRUE)
+ if ((p_cb->features & BTA_AV_FEAT_METADATA) &&
+ (p_vendor->company_id == AVRC_CO_METADATA))
+ {
+ av.meta_msg.p_msg = &p_data->rc_msg.msg;
+ evt = bta_av_proc_meta_cmd (&rc_rsp, &p_data->rc_msg, &ctype);
+ }
+ else
+#endif
+ 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)
+ {
+#if (AVRC_METADATA_INCLUDED == TRUE)
+ if ((p_cb->features & BTA_AV_FEAT_METADATA) &&
+ (p_vendor->company_id == AVRC_CO_METADATA))
+ {
+ av.meta_msg.p_msg = &p_data->rc_msg.msg;
+ evt = BTA_AV_META_MSG_EVT;
+ }
+ else
+#endif
+ 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)
+ {
+ /* reject it */
+ 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);
+ }
+ }
+#if (AVRC_METADATA_INCLUDED == TRUE)
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ else if (p_data->rc_msg.opcode == AVRC_OP_BROWSE)
+ {
+ /* set up for callback */
+ av.meta_msg.code = p_data->rc_msg.msg.hdr.ctype;
+ av.meta_msg.company_id = p_vendor->company_id;
+ av.meta_msg.label = p_data->rc_msg.label;
+ av.meta_msg.p_data = p_data->rc_msg.msg.browse.p_browse_data;
+ av.meta_msg.len = p_data->rc_msg.msg.browse.browse_len;
+ av.meta_msg.p_msg = &p_data->rc_msg.msg;
+ evt = BTA_AV_META_MSG_EVT;
+ }
+#endif
+#endif
+
+ if (evt == 0 && rc_rsp.rsp.status != BTA_AV_STS_NO_RSP)
+ {
+ if (!p_pkt)
+ {
+ rc_rsp.rsp.opcode = p_data->rc_msg.opcode;
+ res = AVRC_BldResponse (0, &rc_rsp, &p_pkt);
+ }
+ if (p_pkt)
+ AVRC_MsgReq (p_data->rc_msg.handle, p_data->rc_msg.label, ctype, p_pkt);
+ }
+#endif
+
+ /* call callback */
+ if (evt != 0)
+ {
+ av.remote_cmd.rc_handle = p_data->rc_msg.handle;
+ (*p_cb->p_cback)(evt, &av);
+#if (AVRC_METADATA_INCLUDED == TRUE)
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+#if (AVCT_BROWSE_INCLUDED == TRUE)
+ /* If the application does not free the buffer or claim the ownership, free the buffer now */
+ if (p_data->rc_msg.opcode == AVRC_OP_BROWSE)
+ utl_freebuf((void **)&p_data->rc_msg.msg.browse.p_browse_pkt);
+#endif
+#endif
+#endif
+ }
+}
+
+/*******************************************************************************
+**
+** 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];
+ if ( p_scbi && (bta_av_cb.audio_streams & BTA_AV_HNDL_TO_MSK(i)) /* scb is used and started */
+ && 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);
+
+ bta_sys_start_timer(&p_cb->sig_tmr, BTA_AV_SIG_TIMER_EVT, BTA_AV_SIG_TIME_VAL);
+
+ /* 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 /* AV_INCLUDED */
diff --git a/bta/av/bta_av_api.c b/bta/av/bta_av_api.c
new file mode 100644
index 0000000..3bb59f7
--- /dev/null
+++ b/bta/av/bta_av_api.c
@@ -0,0 +1,568 @@
+/*****************************************************************************
+**
+** Name: bta_av_api.c
+**
+** Description: This is the implementation of the API for the advanced
+** audio/video (AV) subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+#if defined(AV_INCLUDED) && (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 /* AV_INCLUDED */
diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c
new file mode 100644
index 0000000..bb01366
--- /dev/null
+++ b/bta/av/bta_av_cfg.c
@@ -0,0 +1,276 @@
+/*****************************************************************************
+**
+** Name: bta_av_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for advanced audio/video
+**
+** Copyright (c) 2005-2009, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+#include "gki.h"
+#include "bta_api.h"
+#include "bta_av_int.h"
+
+#ifndef BTA_AV_VDP_INCLUDED
+#define BTA_AV_VDP_INCLUDED TRUE
+#endif
+
+#if ((VDP_INCLUDED == FALSE) && (BTA_AV_VDP_INCLUDED == TRUE))
+#undef BTA_AV_VDP_INCLUDED
+#define BTA_AV_VDP_INCLUDED FALSE
+#endif
+
+#ifndef BTA_AV_RC_PASS_RSP_CODE
+#define BTA_AV_RC_PASS_RSP_CODE BTA_AV_RSP_NOT_IMPL
+#endif
+
+#if (BTA_AV_VDP_INCLUDED == TRUE)
+#define BTA_AV_NUM_A2DP_STRS (BTA_AV_NUM_STRS - 1)
+#else
+#define BTA_AV_NUM_A2DP_STRS (BTA_AV_NUM_STRS)
+#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 */
+#if AVRC_ADV_CTRL_INCLUDED == TRUE
+#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1|AVRC_SUPF_TG_APP_SETTINGS|AVRC_SUPF_TG_BROWSE|AVRC_SUPF_TG_MULTI_PLAYER)
+#else
+#if AVRC_METADATA_INCLUDED == TRUE
+#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1|AVRC_SUPF_TG_APP_SETTINGS)
+#else
+#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1)
+#endif
+#endif
+
+
+/*
+ * 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,
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+ AVRC_EVT_NOW_PLAYING_CHANGE,
+ AVRC_EVT_AVAL_PLAYERS_CHANGE,
+ AVRC_EVT_ADDR_PLAYER_CHANGE,
+// AVRC_EVT_UIDS_CHANGE,
+ AVRC_EVT_VOLUME_CHANGE
+#endif
+};
+#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 */
+#if AVRC_ADV_CTRL_INCLUDED == TRUE
+#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1|AVRC_SUPF_TG_APP_SETTINGS|AVRC_SUPF_TG_GROUP_NAVI|AVRC_SUPF_TG_BROWSE|AVRC_SUPF_TG_MULTI_PLAYER)
+#else
+#if AVRC_METADATA_INCLUDED == TRUE
+#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1|AVRC_SUPF_TG_APP_SETTINGS|AVRC_SUPF_TG_GROUP_NAVI)
+#else
+#define BTA_AV_RC_SUPF_TG (AVRC_SUPF_TG_CAT1)
+#endif
+#endif
+
+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,
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+ AVRC_EVT_NOW_PLAYING_CHANGE,
+ AVRC_EVT_AVAL_PLAYERS_CHANGE,
+ AVRC_EVT_ADDR_PLAYER_CHANGE,
+ AVRC_EVT_UIDS_CHANGE,
+ AVRC_EVT_VOLUME_CHANGE
+#endif
+};
+
+#ifndef BTA_AV_NUM_RC_EVT_IDS
+#if (AVRC_ADV_CTRL_INCLUDED == TRUE)
+#define BTA_AV_NUM_RC_EVT_IDS 13
+#else
+#define BTA_AV_NUM_RC_EVT_IDS 8
+#endif
+#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 */
+#if AVRC_METADATA_INCLUDED == TRUE
+ 512, /* AVRCP MTU at L2CAP for control channel */
+ BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
+#else
+ 48, /* AVRCP MTU at L2CAP for control channel */
+ BTA_AV_MAX_RC_BR_MTU, /* AVRCP MTU at L2CAP for browsing channel */
+#endif
+ 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 */
+#if BTA_AV_VDP_INCLUDED == TRUE
+ (const tBTA_AV_ACT *)bta_av_vdp_action,/* the action table for VDP */
+ bta_av_reg_vdp /* action function to register VDP */
+#else
+ (const tBTA_AV_ACT *)NULL,/* the action table for VDP */
+ NULL /* action function to register VDP */
+#endif
+};
+
+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..c182948
--- /dev/null
+++ b/bta/av/bta_av_ci.c
@@ -0,0 +1,85 @@
+/*****************************************************************************
+**
+** Name: bta_av_ci.c
+**
+** Description: This is the implementation file for advanced audio/video
+** call-in functions.
+**
+** Copyright (c) 2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..9e7f510
--- /dev/null
+++ b/bta/av/bta_av_int.h
@@ -0,0 +1,706 @@
+/*****************************************************************************
+**
+** Name: bta_av_int.h
+**
+** Description: This is the private interface file for the BTA advanced
+** audio/video.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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"
+
+/*****************************************************************************
+** 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..65c2cfe
--- /dev/null
+++ b/bta/av/bta_av_main.c
@@ -0,0 +1,1318 @@
+/*****************************************************************************
+**
+** Name: bta_av_main.c
+**
+** Description: This is the main implementation file for the BTA
+** advanced audio/video.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+#if defined(AV_INCLUDED) && (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(&reg, 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_AVK_INCLUDED == FALSE)
+ 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
+ }
+#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 *)&registr);
+}
+
+/*******************************************************************************
+**
+** 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)
+{
+ tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
+ if(p_scb)
+ {
+ bta_av_co_video_report_conn(p_data->str_msg.msg.report_conn.err_param,
+ p_scb->avdt_handle);
+ }
+}
+#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 /* AV_INCLUDED */
diff --git a/bta/av/bta_av_ssm.c b/bta/av/bta_av_ssm.c
new file mode 100644
index 0000000..ec3532a
--- /dev/null
+++ b/bta/av/bta_av_ssm.c
@@ -0,0 +1,587 @@
+/*****************************************************************************
+**
+** Name: bta_av_ssm.c
+**
+** Description: This is the stream state machine for the BTA
+** advanced audio/video.
+**
+** Copyright (c) 2004, Broadcom Inc., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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_SDP_FAILED, BTA_AV_SIGNORE, BTA_AV_INIT_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/dg/bta_dg_act.c b/bta/dg/bta_dg_act.c
new file mode 100644
index 0000000..f01d606
--- /dev/null
+++ b/bta/dg/bta_dg_act.c
@@ -0,0 +1,900 @@
+/*****************************************************************************
+**
+** Name: bta_dg_act.c
+**
+** Description: This file contains the data gateway action functions
+** for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_DG_INCLUDED) && (BTA_DG_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_dg_api.h"
+#include "bta_dg_int.h"
+#include "bta_dg_co.h"
+#include "btm_api.h"
+#include "sdp_api.h"
+#include "dun_api.h"
+#include "gki.h"
+#include "bd.h"
+
+/* Event mask for RfCOMM port callback */
+#define BTA_DG_PORT_EV_MASK (PORT_EV_FC | PORT_EV_FCS | PORT_EV_RXCHAR | \
+ PORT_EV_TXEMPTY | PORT_EV_CTS | PORT_EV_DSR | \
+ PORT_EV_RING | PORT_EV_CTSS | PORT_EV_DSRS)
+
+/* RX and TX data flow mask */
+#define BTA_DG_RX_MASK 0x0F
+#define BTA_DG_TX_MASK 0xF0
+
+/* size of database for service discovery */
+#define BTA_DG_DISC_BUF_SIZE 450
+
+/* size of discovery db taking into account tBTA_DG_SDP_DB */
+#define BTA_DG_SDP_DB_SIZE (BTA_DG_DISC_BUF_SIZE - (UINT32) &((tBTA_DG_SDP_DB *) 0)->db)
+
+/* UUID lookup table */
+const UINT16 bta_dg_uuid[] =
+{
+ UUID_SERVCLASS_SERIAL_PORT, /* BTA_SPP_SERVICE_ID */
+ UUID_SERVCLASS_DIALUP_NETWORKING, /* BTA_DUN_SERVICE_ID */
+ UUID_SERVCLASS_FAX, /* BTA_FAX_SERVICE_ID */
+ UUID_SERVCLASS_LAN_ACCESS_USING_PPP /* BTA_LAP_SERVICE_ID */
+};
+
+/* BTM service ID lookup table */
+const UINT8 bta_dg_sec_id[] =
+{
+ BTM_SEC_SERVICE_SERIAL_PORT, /* BTA_SPP_SERVICE_ID */
+ BTM_SEC_SERVICE_DUN, /* BTA_DUN_SERVICE_ID */
+ BTM_SEC_SERVICE_FAX, /* BTA_FAX_SERVICE_ID */
+ BTM_SEC_SERVICE_SERIAL_PORT /* BTA_LAP_SERVICE_ID */
+};
+
+/* RS-232 signal lookup table */
+const UINT8 bta_dg_sig[2][4] =
+{
+ {PORT_CLR_DTRDSR, PORT_CLR_CTSRTS, PORT_CLR_RI, PORT_CLR_DCD},
+ {PORT_SET_DTRDSR, PORT_SET_CTSRTS, PORT_SET_RI, PORT_SET_DCD}
+};
+
+/* declare sdp callback functions */
+void bta_dg_sdp_cback_1(UINT16 status);
+void bta_dg_sdp_cback_2(UINT16 status);
+void bta_dg_sdp_cback_3(UINT16 status);
+void bta_dg_sdp_cback_4(UINT16 status);
+void bta_dg_sdp_cback_5(UINT16 status);
+void bta_dg_sdp_cback_6(UINT16 status);
+void bta_dg_sdp_cback_7(UINT16 status);
+void bta_dg_sdp_cback_8(UINT16 status);
+
+/* SDP callback function table */
+typedef tSDP_DISC_CMPL_CB *tBTA_DG_SDP_CBACK;
+const tBTA_DG_SDP_CBACK bta_dg_sdp_cback_tbl[] =
+{
+ bta_dg_sdp_cback_1,
+ bta_dg_sdp_cback_2,
+ bta_dg_sdp_cback_3,
+ bta_dg_sdp_cback_4,
+ bta_dg_sdp_cback_5,
+ bta_dg_sdp_cback_6,
+ bta_dg_sdp_cback_7,
+ bta_dg_sdp_cback_8
+};
+
+/*******************************************************************************
+**
+** Function bta_dg_sdp_cback
+**
+** Description SDP callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dg_sdp_cback(UINT16 status, UINT8 idx)
+{
+ tBTA_DG_DISC_RESULT *p_buf;
+
+ APPL_TRACE_DEBUG1("bta_dg_sdp_cback status:0x%x", status);
+
+ if ((p_buf = (tBTA_DG_DISC_RESULT *) GKI_getbuf(sizeof(tBTA_DG_DISC_RESULT))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DG_DISC_RESULT_EVT;
+ p_buf->hdr.layer_specific = idx;
+ p_buf->status = status;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_sdp_cback_1 to 8
+**
+** 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_dg_sdp_cback_1(UINT16 status) {bta_dg_sdp_cback(status, 1);}
+void bta_dg_sdp_cback_2(UINT16 status) {bta_dg_sdp_cback(status, 2);}
+void bta_dg_sdp_cback_3(UINT16 status) {bta_dg_sdp_cback(status, 3);}
+void bta_dg_sdp_cback_4(UINT16 status) {bta_dg_sdp_cback(status, 4);}
+void bta_dg_sdp_cback_5(UINT16 status) {bta_dg_sdp_cback(status, 5);}
+void bta_dg_sdp_cback_6(UINT16 status) {bta_dg_sdp_cback(status, 6);}
+void bta_dg_sdp_cback_7(UINT16 status) {bta_dg_sdp_cback(status, 7);}
+void bta_dg_sdp_cback_8(UINT16 status) {bta_dg_sdp_cback(status, 8);}
+
+/*******************************************************************************
+**
+** Function bta_dg_port_cback
+**
+** Description RFCOMM Port callback
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dg_port_cback(UINT32 code, UINT16 port_handle)
+{
+ tBTA_DG_RFC_PORT *p_buf;
+ tBTA_DG_SCB *p_scb;
+
+ /* set flow control state directly */
+ if (code & PORT_EV_FC)
+ {
+ if ((p_scb = bta_dg_scb_by_handle(port_handle)) != NULL)
+ {
+ p_scb->rfc_enable = ((code & PORT_EV_FCS) == PORT_EV_FCS);
+
+ if ((p_scb->flow_mask & BTA_DG_RX_MASK) == BTA_DG_RX_PUSH_BUF)
+ {
+ bta_dg_co_rx_flow(port_handle, p_scb->app_id, p_scb->rfc_enable);
+ }
+ }
+ }
+
+ if ((p_buf = (tBTA_DG_RFC_PORT *) GKI_getbuf(sizeof(tBTA_DG_RFC_PORT))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DG_RFC_PORT_EVT;
+ p_buf->hdr.layer_specific = port_handle;
+ p_buf->code = code;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_mgmt_cback
+**
+** Description RFCOMM management callback
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dg_mgmt_cback(UINT32 code, UINT16 port_handle)
+{
+ BT_HDR *p_buf;
+ tBTA_DG_SCB *p_scb;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->layer_specific = port_handle;
+
+ if (code == PORT_SUCCESS)
+ {
+ p_buf->event = BTA_DG_RFC_OPEN_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+ else
+ {
+ if ((p_scb = bta_dg_scb_by_handle(port_handle)) != NULL)
+ {
+/* APPL_TRACE_EVENT6("DG Port Close: handle %d, scb %d, app_id %d, in_use %d, scn %d, state %d",
+ port_handle, bta_dg_scb_to_idx(p_scb), p_scb->app_id, p_scb->in_use, p_scb->scn, p_scb->state);
+*/
+ p_buf->event = BTA_DG_RFC_CLOSE_EVT;
+
+ /* Execute close event before exiting RFC callback to avoid a race
+ condition where RFC could reallocate port_handle before DG can
+ process the event queue
+ */
+ bta_dg_sm_execute(p_scb, p_buf->event, (tBTA_DG_DATA *) p_buf);
+ }
+ else
+ {
+ APPL_TRACE_WARNING1("DG received RFC Close for unknown handle (%d)",
+ port_handle);
+ }
+
+ GKI_freebuf(p_buf);
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("DG RFC callback: No Resources!");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_data_cback
+**
+** Description RFCOMM data callback. This callback is used when a server
+** TX data path is configured for BTA_DG_TX_PUSH to transfer
+** data directly from RFCOMM to the phone.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static int bta_dg_data_cback(UINT16 port_handle, void *p_data, UINT16 len)
+{
+ tBTA_DG_SCB *p_scb;
+
+ if ((p_scb = bta_dg_scb_by_handle(port_handle)) != NULL)
+ {
+ bta_dg_co_tx_write(port_handle, p_scb->app_id, (UINT8 *) p_data, len);
+ }
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_setup_port
+**
+** Description Setup RFCOMM port for use by DG.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dg_setup_port(tBTA_DG_SCB *p_scb)
+{
+ /* store scb in handle lookup table */
+ bta_dg_cb.hdl_to_scb[p_scb->port_handle - 1] = bta_dg_scb_to_idx(p_scb);
+
+ /* call application init call-out */
+ p_scb->flow_mask = bta_dg_co_init(p_scb->port_handle, p_scb->app_id);
+
+ /* set up port and data callbacks */
+ if ((p_scb->flow_mask & BTA_DG_TX_MASK) == BTA_DG_TX_PUSH)
+ {
+ PORT_SetDataCallback(p_scb->port_handle, bta_dg_data_cback);
+ }
+ PORT_SetEventMask(p_scb->port_handle, BTA_DG_PORT_EV_MASK);
+ PORT_SetEventCallback(p_scb->port_handle, bta_dg_port_cback);
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_setup_server
+**
+** Description This function initializes values of the DG scb and sets up
+** the SDP record for the server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_setup_server(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ tBTA_DG_LISTEN listen;
+ tBTA_DG_SCB *p_match;
+
+ /* initialize control block */
+ p_scb->service_id = p_data->api_listen.service;
+ p_scb->sec_mask = p_data->api_listen.sec_mask;
+ p_scb->app_id = p_data->api_listen.app_id;
+ p_scb->is_server = TRUE;
+ BCM_STRNCPY_S(p_scb->name, BTA_SERVICE_NAME_LEN+1, p_data->api_listen.name, BTA_SERVICE_NAME_LEN);
+ p_scb->name[BTA_SERVICE_NAME_LEN] = '\0';
+
+ /* if existing matching server */
+ if ((p_match = bta_dg_server_match(p_scb)) != NULL)
+ {
+ /* set SCN same as existing matching server */
+ p_scb->scn = p_match->scn;
+
+ /* copy sdp handle in order to unregister it from any server instance (being last) */
+ p_scb->sdp_handle = p_match->sdp_handle;
+ }
+ else
+ {
+ /* allocate SDP record and SCN */
+ p_scb->sdp_handle = SDP_CreateRecord();
+ p_scb->scn = BTM_AllocateSCN();
+ APPL_TRACE_DEBUG2( "bta_dg_setup_server: x%x, scn:%d", p_scb->sdp_handle, p_scb->scn);
+
+ /* set up sdp record */
+ DUN_AddRecord(bta_dg_uuid[p_scb->service_id - BTA_SPP_SERVICE_ID],
+ p_data->api_listen.name, p_scb->scn, 0, p_scb->sdp_handle);
+
+ bta_sys_add_uuid(bta_dg_uuid[p_scb->service_id - BTA_SPP_SERVICE_ID]);
+ }
+
+ /* Listen on RFCOMM port */
+ bta_dg_listen(p_scb, p_data);
+
+ /* call app callback with listen event */
+ listen.handle = bta_dg_scb_to_idx(p_scb);
+ listen.app_id = p_scb->app_id;
+ (*bta_dg_cb.p_cback)(BTA_DG_LISTEN_EVT, (tBTA_DG *) &listen);
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_listen
+**
+** Description Call DUN_Listen to set up a server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_listen(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ UINT8 lkup_id = p_scb->service_id - BTA_SPP_SERVICE_ID;
+
+ /* Listen on RFCOMM port */
+ if (DUN_Listen(bta_dg_uuid[lkup_id], p_scb->name, p_scb->scn, p_bta_dg_cfg->mtu[lkup_id],
+ p_scb->sec_mask, &p_scb->port_handle, bta_dg_mgmt_cback)
+ == DUN_SUCCESS)
+ {
+ bta_dg_setup_port(p_scb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_del_record
+**
+** Description Delete SDP record.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_del_record(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ /* if no existing matching server */
+ if (bta_dg_server_match(p_scb) == NULL)
+ {
+ APPL_TRACE_DEBUG1( "bta_dg_del_record: x%x", p_scb->sdp_handle);
+ if(p_scb->sdp_handle)
+ SDP_DeleteRecord(p_scb->sdp_handle);
+ bta_sys_remove_uuid( bta_dg_uuid[p_scb->service_id - BTA_SPP_SERVICE_ID] );
+ BTM_FreeSCN(p_scb->scn);
+ BTM_SecClrService(bta_dg_sec_id[p_scb->service_id - BTA_SPP_SERVICE_ID]);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_shutdown
+**
+** Description Shut down a server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_shutdown(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ UINT8 status;
+
+ APPL_TRACE_DEBUG1( "bta_dg_shutdown: x%x", p_scb->sdp_handle);
+
+ status = DUN_Shutdown(p_scb->port_handle);
+
+ APPL_TRACE_DEBUG1("DUN shutdown status %d", status);
+
+ bta_dg_del_record(p_scb, p_data);
+
+ /* set shutdown flag */
+ p_scb->dealloc = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_close
+**
+** Description Close RFCOMM connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_close(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ if (p_scb->port_handle)
+ {
+ DUN_Close(p_scb->port_handle);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_set_dealloc
+**
+** Description Set the dealloc flag.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_set_dealloc(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ p_scb->dealloc = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_rx_path
+**
+** Description Handle data on the RX path (data sent from the phone to
+** BTA).
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_rx_path(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ /* if data path configured for rx pull */
+ if ((p_scb->flow_mask & BTA_DG_RX_MASK) == BTA_DG_RX_PULL)
+ {
+ /* if RFCOMM can accept data */
+ if (p_scb->rfc_enable == TRUE)
+ {
+ /* call application callout function for rx path */
+ bta_dg_co_rx_path(p_scb->port_handle, p_scb->app_id, p_scb->mtu);
+ }
+ }
+ /* else data path configured for rx push */
+ else
+ {
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_tx_path
+**
+** Description Handle the TX data path (data sent from BTA to the phone).
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_tx_path(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ BT_HDR *p_buf;
+ UINT16 port_errors;
+ tPORT_STATUS port_status;
+ int status;
+
+ /* if data path configured for tx pull */
+ if ((p_scb->flow_mask & BTA_DG_TX_MASK) == BTA_DG_TX_PULL)
+ {
+ /* call application callout function for tx path */
+ bta_dg_co_tx_path(p_scb->port_handle, p_scb->app_id);
+ }
+ /* if configured for zero copy push */
+ else if ((p_scb->flow_mask & BTA_DG_TX_MASK) == BTA_DG_TX_PUSH_BUF)
+ {
+ /* if app can accept data */
+ while (p_scb->app_enable == TRUE)
+ {
+ /* read data from RFCOMM */
+ if ((status = PORT_Read(p_scb->port_handle, &p_buf)) == PORT_SUCCESS)
+ {
+ if(p_buf == NULL)
+ {
+ return;
+ }
+ /* send data to application */
+ bta_dg_co_tx_writebuf(p_scb->port_handle, p_scb->app_id, p_buf);
+ }
+ else if (status == PORT_LINE_ERR)
+ {
+ PORT_ClearError(p_scb->port_handle, &port_errors, &port_status);
+ return;
+ }
+ else
+ {
+ return;
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_fc_state
+**
+** Description Set the application flow control state.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_fc_state(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ p_scb->app_enable = p_data->ci_tx_flow.enable;
+ PORT_FlowControl(p_scb->port_handle, p_scb->app_enable);
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_writebuf
+**
+** Description Handle a bta_dg_ci_rx_writebuf() and send data to RFCOMM.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_writebuf(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ if ((p_scb->flow_mask & BTA_DG_RX_MASK) == BTA_DG_RX_PUSH_BUF)
+ {
+ PORT_Write(p_scb->port_handle, (BT_HDR *) p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_control
+**
+** Description Pass RS-232 control signals from phone to RFCOMM.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_control(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ int i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (p_data->ci_control.signals & 1)
+ {
+ PORT_Control(p_scb->port_handle, bta_dg_sig[(p_data->ci_control.values & 1)][i]);
+ }
+ p_data->ci_control.signals >>= 1;
+ p_data->ci_control.values >>= 1;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_rfc_control
+**
+** Description Handle a change in RS-232 signals from RFCOMM
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_rfc_control(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ UINT8 signals = 0;
+ UINT8 values = 0;
+ UINT8 port_values = 0;
+
+ PORT_GetModemStatus(p_scb->port_handle, &port_values);
+
+ if (p_data->rfc_port.code & PORT_EV_CTS)
+ {
+ values |= (p_data->rfc_port.code & PORT_EV_CTSS) ? BTA_DG_RTSCTS_ON : BTA_DG_RTSCTS_OFF;
+ signals |= BTA_DG_RTSCTS;
+ }
+ if (p_data->rfc_port.code & PORT_EV_DSR)
+ {
+ values |= (p_data->rfc_port.code & PORT_EV_DSRS) ? BTA_DG_DTRDSR_ON : BTA_DG_DTRDSR_OFF;
+ signals |= BTA_DG_DTRDSR;
+ }
+ if (p_data->rfc_port.code & PORT_EV_RING)
+ {
+ values |= (port_values & PORT_RING_ON);
+ signals |= BTA_DG_RI;
+ }
+
+ bta_dg_co_control(p_scb->port_handle, p_scb->app_id, signals, values);
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_rfc_open
+**
+** Description Handle RFCOMM channel opening.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_rfc_open(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ tPORT_STATUS status;
+ UINT16 lcid;
+ tBTA_DG_OPEN open;
+
+ /* reset flow control state */
+ p_scb->rfc_enable = TRUE;
+ p_scb->app_enable = TRUE;
+
+ /* get mtu of connection */
+ PORT_GetQueueStatus(p_scb->port_handle, &status);
+ p_scb->mtu = status.mtu_size;
+
+ /* call app call-out */
+ bta_dg_co_open(p_scb->port_handle, p_scb->app_id, p_scb->service_id, p_scb->mtu);
+
+ /* get bd addr of peer */
+ PORT_CheckConnection(p_scb->port_handle, open.bd_addr, &lcid);
+
+ /* call app callback with open event */
+ open.handle = bta_dg_scb_to_idx(p_scb);
+ open.service = p_scb->service_id;
+ open.app_id = p_scb->app_id;
+
+ bdcpy(p_scb->peer_addr, open.bd_addr);
+
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_DG ,p_scb->app_id, open.bd_addr);
+
+ (*bta_dg_cb.p_cback)(BTA_DG_OPEN_EVT, (tBTA_DG *) &open);
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_rfc_close
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_rfc_close(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ tBTA_DG_CLOSE close;
+
+ /* call app call-out */
+ if (p_scb->port_handle != 0)
+ {
+ bta_dg_co_close(p_scb->port_handle, p_scb->app_id);
+ }
+
+ /* call app callback */
+ close.handle = bta_dg_scb_to_idx(p_scb);
+ close.app_id = p_scb->app_id;
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_DG ,p_scb->app_id, p_scb->peer_addr);
+
+ (*bta_dg_cb.p_cback)(BTA_DG_CLOSE_EVT, (tBTA_DG *) &close);
+
+ /* if not shutting down, initialize the server */
+ if (p_scb->dealloc == FALSE)
+ {
+ bta_dg_setup_port(p_scb);
+ }
+ /* else dealloc control block */
+ else
+ {
+ bta_dg_scb_dealloc(p_scb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_dealloc
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_dealloc(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1( "bta_dg_dealloc: x%x", p_scb->sdp_handle);
+ bta_dg_scb_dealloc(p_scb);
+}
+/*******************************************************************************
+**
+** Function bta_dg_disc_result
+**
+** Description Process a discovery result.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_disc_result(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ tSDP_DISC_REC *p_rec = NULL;
+ tSDP_DISC_ATTR *p_attr;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT16 name_len;
+ char *p_name;
+ UINT16 evt = BTA_DG_DISC_FAIL_EVT;
+
+
+ if (p_data->disc_result.status == SDP_SUCCESS || p_data->disc_result.status == SDP_DB_FULL)
+ {
+ /* 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,
+ bta_dg_uuid[p_scb->service_id - BTA_SPP_SERVICE_ID], p_rec)) == NULL)
+ {
+ break;
+ }
+
+ /* get scn from proto desc list; if not found, go to next record */
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ p_scb->scn = (UINT8) pe.params[0];
+ }
+ else
+ {
+ continue;
+ }
+
+ /* if service name provided for match */
+ if (p_scb->p_disc->name[0] != 0)
+ {
+ /* get service name */
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+ {
+ /* check if name matches */
+ p_name = (char *) p_attr->attr_value.v.array;
+ name_len = SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+ if (strncmp(p_scb->p_disc->name, p_name, name_len) == 0)
+ {
+ /* name matches; we found it */
+ evt = BTA_DG_DISC_OK_EVT;
+ break;
+ }
+ else
+ {
+ /* name does not match; continue */
+ continue;
+ }
+ }
+ }
+ /* else name match not required; we're done */
+ else
+ {
+ evt = BTA_DG_DISC_OK_EVT;
+ break;
+ }
+ }
+ }
+
+ /* send ourselves event to process disc ok or fail */
+ bta_dg_sm_execute(p_scb, evt, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_do_disc
+**
+** Description Do service discovery.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_do_disc(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ tBTA_DG_OPENING opening;
+ tSDP_UUID uuid_list;
+ UINT16 attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
+ ATTR_ID_PROTOCOL_DESC_LIST,
+ ATTR_ID_SERVICE_NAME};
+
+ /* allocate buffer for sdp database */
+ if ((p_scb->p_disc = (tBTA_DG_SDP_DB *) GKI_getbuf(BTA_DG_DISC_BUF_SIZE)) != NULL)
+ {
+ /* store parameters */
+ BCM_STRCPY_S(p_scb->p_disc->name, sizeof(p_scb->p_disc->name), p_data->api_open.name);
+ bdcpy(p_scb->peer_addr, p_data->api_open.bd_addr);
+ p_scb->sec_mask = p_data->api_open.sec_mask;
+ p_scb->service_id = p_data->api_open.service;
+ p_scb->app_id = p_data->api_open.app_id;
+
+ /* initialize some scb parameters */
+ p_scb->dealloc = TRUE;
+ p_scb->port_handle = 0;
+
+
+ bta_sys_app_open(BTA_ID_DG, p_scb->app_id, p_scb->peer_addr);
+
+ /* set up service discovery database */
+ uuid_list.len = LEN_UUID_16;
+ uuid_list.uu.uuid16 = bta_dg_uuid[p_scb->service_id - BTA_SPP_SERVICE_ID];
+
+ /* coverity[OVERRUN_STATIC] False-positive: All pointers are ok. len parameter size (in bytes) of the memory must be larger than sizeof(tSDP_DISCOVERY_DB) */
+ SDP_InitDiscoveryDb(&p_scb->p_disc->db, BTA_DG_SDP_DB_SIZE, 1, &uuid_list, 3, attr_list);
+
+ /* initiate service discovery */
+ if (SDP_ServiceSearchAttributeRequest(p_scb->peer_addr, &p_scb->p_disc->db,
+ bta_dg_sdp_cback_tbl[bta_dg_scb_to_idx(p_scb) - 1]))
+ {
+ /* call callback with opening event */
+ opening.handle = bta_dg_scb_to_idx(p_scb);
+ opening.app_id = p_scb->app_id;
+ (*bta_dg_cb.p_cback)(BTA_DG_OPENING_EVT, (tBTA_DG *) &opening);
+ }
+ else
+ {
+ bta_dg_sdp_cback(SDP_NO_RESOURCES, bta_dg_scb_to_idx(p_scb));
+ }
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("DG DISC: No Resources!");
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_open
+**
+** Description Open a client connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_open(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ UINT8 lkup_id = p_scb->service_id - BTA_SPP_SERVICE_ID;
+
+ if (DUN_Connect(bta_dg_uuid[lkup_id], p_scb->peer_addr, p_scb->scn, p_bta_dg_cfg->mtu[lkup_id],
+ p_scb->sec_mask, &p_scb->port_handle, bta_dg_mgmt_cback) == DUN_SUCCESS)
+ {
+ bta_dg_setup_port(p_scb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_free_db
+**
+** Description Free discovery database.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_free_db(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data)
+{
+ if (p_scb->p_disc != NULL)
+ {
+ GKI_freebuf(p_scb->p_disc);
+ p_scb->p_disc = NULL;
+ }
+}
+
+#endif /* BTA_DG_INCLUDED */
diff --git a/bta/dg/bta_dg_api.c b/bta/dg/bta_dg_api.c
new file mode 100644
index 0000000..ab4b737
--- /dev/null
+++ b/bta/dg/bta_dg_api.c
@@ -0,0 +1,218 @@
+/*****************************************************************************
+**
+** Name: bta_dg_api.c
+**
+** Description: This is the implementation of the API for the data gateway
+** (DG) subsystem of BTA, Widcomm's Bluetooth application
+** layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_DG_INCLUDED) && (BTA_DG_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_dg_api.h"
+#include "bta_dg_int.h"
+#include "gki.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_dg_reg =
+{
+ bta_dg_hdl_event,
+ BTA_DgDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_DgEnable
+**
+** Description Enable the data gateway service. This function must be
+** called before any other functions in the DG API are called.
+** When the enable operation is complete the callback function
+** will be called with a BTA_DG_ENABLE_EVT. After the DG
+** service is enabled a server can be started by calling
+** BTA_DgListen().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DgEnable(tBTA_DG_CBACK *p_cback)
+{
+ tBTA_DG_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_DG, &bta_dg_reg);
+ GKI_sched_unlock();
+
+ APPL_TRACE_API0( "BTA_DgEnable");
+ if ((p_buf = (tBTA_DG_API_ENABLE *) GKI_getbuf(sizeof(tBTA_DG_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DG_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DgDisable
+**
+** Description Disable the data gateway service. Before calling this
+** function all DG servers must be shut down by calling
+** BTA_DgShutdown().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DgDisable(void)
+{
+ BT_HDR *p_buf;
+
+ APPL_TRACE_API0( "BTA_DgDisable");
+ bta_sys_deregister(BTA_ID_DG);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_DG_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DgListen
+**
+** Description Create a DG server for DUN, FAX or SPP. After creating a
+** server peer devices can open an RFCOMM connection to the
+** server. When the listen operation has started the callback
+** function will be called with a BTA_DG_LISTEN_EVT providing
+** the handle associated with this server. The handle
+** identifies server when calling other DG functions such as
+** BTA_DgClose() or BTA_DgShutdown().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DgListen(tBTA_SERVICE_ID service, tBTA_SEC sec_mask,
+ char *p_service_name, UINT8 app_id)
+{
+ tBTA_DG_API_LISTEN *p_buf;
+
+ APPL_TRACE_API1( "BTA_DgListen %d", service);
+ if ((p_buf = (tBTA_DG_API_LISTEN *) GKI_getbuf(sizeof(tBTA_DG_API_LISTEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DG_API_LISTEN_EVT;
+ BCM_STRNCPY_S(p_buf->name, sizeof(p_buf->name), p_service_name, BTA_SERVICE_NAME_LEN);
+ p_buf->sec_mask = sec_mask;
+ p_buf->service = service;
+ p_buf->app_id = app_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_DgOpen
+**
+** Description Open a DG client connection to a peer device. BTA first
+** searches for the requested service on the peer device. If
+** the service name is specified it will also match the
+** service name. Then BTA initiates an RFCOMM connection to
+** the peer device. The handle associated with the connection
+** is returned with the BTA_DG_OPEN_EVT. If the connection
+** fails or closes at any time the callback function will be
+** called with a BTA_DG_CLOSE_EVT.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DgOpen(BD_ADDR bd_addr, tBTA_SERVICE_ID service, tBTA_SEC sec_mask,
+ char *p_service_name, UINT8 app_id)
+{
+ tBTA_DG_API_OPEN *p_buf;
+
+ APPL_TRACE_API0( "BTA_DgOpen");
+ if ((p_buf = (tBTA_DG_API_OPEN *) GKI_getbuf(sizeof(tBTA_DG_API_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DG_API_OPEN_EVT;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ if (p_service_name != NULL)
+ {
+ BCM_STRNCPY_S(p_buf->name, sizeof(p_buf->name), p_service_name, BTA_SERVICE_NAME_LEN);
+ }
+ else
+ {
+ p_buf->name[0] = '\0';
+ }
+ p_buf->sec_mask = sec_mask;
+ p_buf->service = service;
+ p_buf->app_id = app_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DgClose
+**
+** Description Close a DG server connection to a peer device. BTA will
+** close the RFCOMM connection to the peer device. The server
+** will still be listening for subsequent connections.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DgClose(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ APPL_TRACE_API0( "BTA_DgClose");
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_DG_API_CLOSE_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_DgShutdown
+**
+** Description Shutdown a DG server previously started by calling
+** BTA_DgListen(). The server will no longer be available
+** to peer devices. If there is currently a connection open
+** to the server it will be closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_DgShutdown(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ APPL_TRACE_API0( "BTA_DgShutdown");
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_DG_API_SHUTDOWN_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+#endif /* BTA_DG_INCLUDED */
diff --git a/bta/dg/bta_dg_cfg.c b/bta/dg/bta_dg_cfg.c
new file mode 100644
index 0000000..6822c8d
--- /dev/null
+++ b/bta/dg/bta_dg_cfg.c
@@ -0,0 +1,54 @@
+/*****************************************************************************
+**
+** Name: bta_dg_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the BTA data gateway.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_DG_INCLUDED) && (BTA_DG_INCLUDED == TRUE)
+
+// btla-specific ++
+#include "l2c_api.h"
+#include "rfcdefs.h"
+// btla-specific --
+#include "bta_dg_api.h"
+#include "rfcdefs.h"
+#include "l2c_api.h"
+
+/* RFCOMM MTU for SPP */
+#ifndef BTA_SPP_MTU
+#define BTA_SPP_MTU 330
+#endif
+
+/* RFCOMM MTU for DUN */
+#ifndef BTA_DUN_MTU
+// btla-specific ++
+#define BTA_DUN_MTU (330*3)
+// btla-specific --
+#endif
+
+/* RFCOMM MTU for FAX */
+#ifndef BTA_FAX_MTU
+#define BTA_FAX_MTU 112
+#endif
+
+/* RFCOMM MTU for LAP */
+#ifndef BTA_LAP_MTU
+#define BTA_LAP_MTU 330
+#endif
+
+const tBTA_DG_CFG bta_dg_cfg =
+{
+ {BTA_SPP_MTU, BTA_DUN_MTU, BTA_FAX_MTU, BTA_LAP_MTU},
+
+};
+
+tBTA_DG_CFG *p_bta_dg_cfg = (tBTA_DG_CFG *)&bta_dg_cfg;
+#endif /* BTA_DG_INCLUDED */
diff --git a/bta/dg/bta_dg_ci.c b/bta/dg/bta_dg_ci.c
new file mode 100644
index 0000000..258eafe
--- /dev/null
+++ b/bta/dg/bta_dg_ci.c
@@ -0,0 +1,159 @@
+/*****************************************************************************
+**
+** Name: bta_dg_ci.c
+**
+** Description: This is the implementation file for data gateway call-in
+** functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_api.h"
+#include "bta_dg_api.h"
+#include "bta_dg_ci.h"
+#include "bta_dg_int.h"
+#include "gki.h"
+
+/*******************************************************************************
+**
+** Function bta_dg_ci_tx_ready
+**
+** Description This function sends an event to DG indicating the phone is
+** ready for more data and DG should call bta_dg_co_tx_path().
+** This function is used when the TX data path is configured
+** to use a pull interface.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_ci_tx_ready(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_DG_CI_TX_READY_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_ci_rx_ready
+**
+** Description This function sends an event to DG indicating the phone
+** has data available to send to DG and DG should call
+** bta_dg_co_rx_path(). This function is used when the RX
+** data path is configured to use a pull interface.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_ci_rx_ready(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_DG_CI_RX_READY_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_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_dg_co_tx_write() or
+** bta_dg_co_tx_writebuf(). This function is used when the
+** TX data path is configured to use a push interface.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_ci_tx_flow(UINT16 handle, BOOLEAN enable)
+{
+ tBTA_DG_CI_TX_FLOW *p_buf;
+
+ if ((p_buf = (tBTA_DG_CI_TX_FLOW *) GKI_getbuf(sizeof(tBTA_DG_CI_TX_FLOW))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DG_CI_TX_FLOW_EVT;
+ p_buf->hdr.layer_specific = handle;
+ p_buf->enable = enable;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_ci_rx_write
+**
+** Description This function is called to send data to DG when the RX path
+** is configured to use a push interface. The function copies
+** data to an event buffer and sends it to DG.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_ci_rx_write(UINT16 handle, UINT8 *p_data, UINT16 len)
+{
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_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 DG 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_dg_ci_rx_writebuf(UINT16 handle, BT_HDR *p_buf)
+{
+ p_buf->event = BTA_DG_CI_RX_WRITEBUF_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_ci_control
+**
+** Description This function is called to send RS-232 signal information
+** to DG to be propagated over RFCOMM.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_ci_control(UINT16 handle, UINT8 signals, UINT8 values)
+{
+ tBTA_DG_CI_CONTROL *p_buf;
+
+ if ((p_buf = (tBTA_DG_CI_CONTROL *) GKI_getbuf(sizeof(tBTA_DG_CI_CONTROL))) != NULL)
+ {
+ p_buf->hdr.event = BTA_DG_CI_CONTROL_EVT;
+ p_buf->hdr.layer_specific = handle;
+ p_buf->signals = signals;
+ p_buf->values = values;
+ bta_sys_sendmsg(p_buf);
+ }
+}
diff --git a/bta/dg/bta_dg_int.h b/bta/dg/bta_dg_int.h
new file mode 100644
index 0000000..0f652e4
--- /dev/null
+++ b/bta/dg/bta_dg_int.h
@@ -0,0 +1,220 @@
+/*****************************************************************************
+**
+** Name: bta_dg_int.h
+**
+** Description: This is the private interface file for the BTA data
+** gateway.
+**
+** Copyright (c) 2003-2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_DG_INT_H
+#define BTA_DG_INT_H
+
+#include "bta_sys.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+
+/* DG events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_DG_API_CLOSE_EVT = BTA_SYS_EVT_START(BTA_ID_DG),
+ BTA_DG_API_SHUTDOWN_EVT,
+ BTA_DG_API_LISTEN_EVT,
+ BTA_DG_API_OPEN_EVT,
+ BTA_DG_CI_TX_READY_EVT,
+ BTA_DG_CI_RX_READY_EVT,
+ BTA_DG_CI_TX_FLOW_EVT,
+ BTA_DG_CI_RX_WRITEBUF_EVT,
+ BTA_DG_CI_CONTROL_EVT,
+ BTA_DG_RFC_OPEN_EVT,
+ BTA_DG_RFC_CLOSE_EVT,
+ BTA_DG_RFC_TX_READY_EVT,
+ BTA_DG_RFC_RX_READY_EVT,
+ BTA_DG_RFC_FC_EVT,
+ BTA_DG_RFC_CONTROL_EVT,
+ BTA_DG_DISC_RESULT_EVT,
+ BTA_DG_DISC_OK_EVT,
+ BTA_DG_DISC_FAIL_EVT,
+
+ /* these events are handled outside of the state machine */
+ BTA_DG_API_DISABLE_EVT,
+ BTA_DG_API_ENABLE_EVT,
+ BTA_DG_RFC_PORT_EVT
+};
+
+/*****************************************************************************
+** Data types
+*****************************************************************************/
+
+/* data type for BTA_DG_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ tBTA_DG_CBACK *p_cback; /* DG callback function */
+} tBTA_DG_API_ENABLE;
+
+/* data type for BTA_DG_API_LISTEN_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ char name[BTA_SERVICE_NAME_LEN+1]; /* Service name */
+ tBTA_SEC sec_mask; /* Security mask */
+ tBTA_SERVICE_ID service; /* Service ID */
+ UINT8 app_id; /* Application ID */
+} tBTA_DG_API_LISTEN;
+
+/* data type for BTA_DG_API_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ char name[BTA_SERVICE_NAME_LEN+1]; /* Service name */
+ BD_ADDR bd_addr; /* Peer address */
+ tBTA_SEC sec_mask; /* Security mask */
+ tBTA_SERVICE_ID service; /* Service ID */
+ UINT8 app_id; /* Application ID */
+} tBTA_DG_API_OPEN;
+
+/* data type for BTA_DG_CI_TX_FLOW_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ BOOLEAN enable; /* Flow control setting */
+} tBTA_DG_CI_TX_FLOW;
+
+/* data type for BTA_DG_CI_CONTROL_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ UINT8 signals; /* RS-232 signals */
+ UINT8 values; /* RS-232 signal values */
+} tBTA_DG_CI_CONTROL;
+
+/* data type for BTA_DG_RFC_FC_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ BOOLEAN enable; /* TRUE if data flow enabled */
+} tBTA_DG_RFC_FC;
+
+/* data type for BTA_DG_RFC_PORT_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ UINT32 code; /* RFCOMM port callback event code mask */
+} tBTA_DG_RFC_PORT;
+
+/* data type for BTA_DG_DISC_RESULT_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ UINT16 status; /* SDP status */
+} tBTA_DG_DISC_RESULT;
+
+/* union of all data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_DG_API_ENABLE api_enable;
+ tBTA_DG_API_LISTEN api_listen;
+ tBTA_DG_API_OPEN api_open;
+ tBTA_DG_CI_TX_FLOW ci_tx_flow;
+ tBTA_DG_CI_CONTROL ci_control;
+ tBTA_DG_RFC_FC rfc_fc;
+ tBTA_DG_RFC_PORT rfc_port;
+ tBTA_DG_DISC_RESULT disc_result;
+} tBTA_DG_DATA;
+
+/* type used to store temporary sdp data */
+typedef struct
+{
+ char name[BTA_SERVICE_NAME_LEN+1]; /* Service name */
+ tSDP_DISCOVERY_DB db; /* Discovery database */
+} tBTA_DG_SDP_DB;
+
+/* state machine control block */
+typedef struct
+{
+ char name[BTA_SERVICE_NAME_LEN+1]; /* Service name */
+ BD_ADDR peer_addr; /* BD address of peer device */
+ tBTA_DG_SDP_DB *p_disc; /* pointer to sdp discovery db */
+ UINT32 sdp_handle; /* SDP record handle */
+ UINT16 port_handle; /* RFCOMM port handle */
+ UINT16 mtu; /* RFCOMM MTU */
+ tBTA_SERVICE_ID service_id; /* Profile service ID */
+ tBTA_SEC sec_mask; /* Security mask */
+ BOOLEAN rfc_enable; /* RFCOMM flow control state */
+ BOOLEAN app_enable; /* Application flow control state */
+ BOOLEAN in_use; /* TRUE if SCB in use */
+ BOOLEAN dealloc; /* TRUE if service shutting down */
+ BOOLEAN is_server; /* TRUE if scb is for server */
+ UINT8 state; /* State machine state */
+ UINT8 app_id; /* Application ID */
+ UINT8 scn; /* Server channel number */
+ UINT8 flow_mask; /* Data flow mask */
+} tBTA_DG_SCB;
+
+/* main control block */
+typedef struct
+{
+ tBTA_DG_SCB scb[BTA_DG_NUM_CONN]; /* state machine control blocks */
+ UINT8 hdl_to_scb[MAX_RFC_PORTS+1];/* port to state machine lookup table */
+ tBTA_DG_CBACK *p_cback; /* DG callback function */
+} tBTA_DG_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* DG control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DG_CB bta_dg_cb;
+#else
+extern tBTA_DG_CB *bta_dg_cb_ptr;
+#define bta_dg_cb (*bta_dg_cb_ptr)
+#endif
+
+/* DG configuration constants */
+extern tBTA_DG_CFG * p_bta_dg_cfg;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern void bta_dg_scb_dealloc(tBTA_DG_SCB *p_scb);
+extern UINT8 bta_dg_scb_to_idx(tBTA_DG_SCB *p_scb);
+extern tBTA_DG_SCB *bta_dg_scb_by_idx(UINT16 idx);
+extern tBTA_DG_SCB *bta_dg_scb_by_handle(UINT16 handle);
+extern tBTA_DG_SCB *bta_dg_server_match(tBTA_DG_SCB *p_srv);
+extern BOOLEAN bta_dg_hdl_event(BT_HDR *p_msg);
+extern void bta_dg_sm_execute(tBTA_DG_SCB *p_scb, UINT16 event, tBTA_DG_DATA *p_data);
+
+/* action functions */
+extern void bta_dg_setup(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_listen(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_del_record(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_shutdown(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_close(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_set_dealloc(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_rx_path(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_tx_path(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_fc_state(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_writebuf(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_control(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_rfc_control(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_rfc_open(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_rfc_close(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_dealloc(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_disc_result(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_do_disc(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_open(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_free_db(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+extern void bta_dg_setup_server(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+
+
+#endif /* BTA_DG_INT_H */
diff --git a/bta/dg/bta_dg_main.c b/bta/dg/bta_dg_main.c
new file mode 100644
index 0000000..63e6db5
--- /dev/null
+++ b/bta/dg/bta_dg_main.c
@@ -0,0 +1,597 @@
+/*****************************************************************************
+**
+** Name: bta_dg_main.c
+**
+** Description: This file contains the data gateway main functions and
+** state machine.
+**
+** Copyright (c) 2003-2006, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_DG_INCLUDED) && (BTA_DG_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_dg_api.h"
+#include "bta_dg_int.h"
+#include "port_api.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+ BTA_DG_INIT_ST,
+ BTA_DG_OPENING_ST,
+ BTA_DG_OPEN_ST,
+ BTA_DG_CLOSING_ST
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_DG_DEL_RECORD,
+ BTA_DG_SHUTDOWN,
+ BTA_DG_CLOSE,
+ BTA_DG_SET_DEALLOC,
+ BTA_DG_RX_PATH,
+ BTA_DG_TX_PATH,
+ BTA_DG_FC_STATE,
+ BTA_DG_WRITEBUF,
+ BTA_DG_CONTROL,
+ BTA_DG_RFC_CONTROL,
+ BTA_DG_RFC_OPEN,
+ BTA_DG_RFC_CLOSE,
+ BTA_DG_DEALLOC,
+ BTA_DG_DISC_RESULT,
+ BTA_DG_DO_DISC,
+ BTA_DG_OPEN,
+ BTA_DG_FREE_DB,
+ BTA_DG_SETUP_SERVER,
+ BTA_DG_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_DG_ACTION)(tBTA_DG_SCB *p_scb, tBTA_DG_DATA *p_data);
+
+/* action function list */
+const tBTA_DG_ACTION bta_dg_action[] =
+{
+ bta_dg_del_record,
+ bta_dg_shutdown,
+ bta_dg_close,
+ bta_dg_set_dealloc,
+ bta_dg_rx_path,
+ bta_dg_tx_path,
+ bta_dg_fc_state,
+ bta_dg_writebuf,
+ bta_dg_control,
+ bta_dg_rfc_control,
+ bta_dg_rfc_open,
+ bta_dg_rfc_close,
+ bta_dg_dealloc,
+ bta_dg_disc_result,
+ bta_dg_do_disc,
+ bta_dg_open,
+ bta_dg_free_db,
+ bta_dg_setup_server
+};
+
+/* state table information */
+#define BTA_DG_ACTIONS 2 /* number of actions */
+#define BTA_DG_NEXT_STATE 2 /* position of next state */
+#define BTA_DG_NUM_COLS 3 /* number of columns in state tables */
+
+/* state table for init state */
+const UINT8 bta_dg_st_init[][BTA_DG_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* API_CLOSE_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* API_SHUTDOWN_EVT */ {BTA_DG_SHUTDOWN, BTA_DG_DEALLOC, BTA_DG_INIT_ST},
+/* API_LISTEN_EVT */ {BTA_DG_SETUP_SERVER, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* API_OPEN_EVT */ {BTA_DG_DO_DISC, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* CI_TX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* CI_RX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* CI_TX_FLOW_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* CI_RX_WRITEBUF_EVT */ {BTA_DG_WRITEBUF, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* CI_CONTROL_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* RFC_OPEN_EVT */ {BTA_DG_RFC_OPEN, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* RFC_CLOSE_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* RFC_TX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* RFC_RX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* RFC_FC_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* RFC_CONTROL_EVT */ {BTA_DG_RFC_CONTROL, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* DISC_RESULT_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* DISC_OK_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* DISC_FAIL_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_INIT_ST}
+};
+
+/* state table for opening state */
+const UINT8 bta_dg_st_opening[][BTA_DG_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* API_CLOSE_EVT */ {BTA_DG_CLOSE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* API_SHUTDOWN_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* API_LISTEN_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* API_OPEN_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* CI_TX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* CI_RX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* CI_TX_FLOW_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* CI_RX_WRITEBUF_EVT */ {BTA_DG_WRITEBUF, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* CI_CONTROL_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* RFC_OPEN_EVT */ {BTA_DG_RFC_OPEN, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* RFC_CLOSE_EVT */ {BTA_DG_RFC_CLOSE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* RFC_TX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* RFC_RX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* RFC_FC_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* RFC_CONTROL_EVT */ {BTA_DG_RFC_CONTROL, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* DISC_RESULT_EVT */ {BTA_DG_DISC_RESULT, BTA_DG_IGNORE, BTA_DG_OPENING_ST},
+/* DISC_OK_EVT */ {BTA_DG_FREE_DB, BTA_DG_OPEN, BTA_DG_OPENING_ST},
+/* DISC_FAIL_EVT */ {BTA_DG_FREE_DB, BTA_DG_RFC_CLOSE, BTA_DG_INIT_ST}
+};
+
+/* state table for open state */
+const UINT8 bta_dg_st_open[][BTA_DG_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* API_CLOSE_EVT */ {BTA_DG_CLOSE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* API_SHUTDOWN_EVT */ {BTA_DG_SHUTDOWN, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* API_LISTEN_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* API_OPEN_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* CI_TX_READY_EVT */ {BTA_DG_TX_PATH, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* CI_RX_READY_EVT */ {BTA_DG_RX_PATH, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* CI_TX_FLOW_EVT */ {BTA_DG_FC_STATE, BTA_DG_TX_PATH, BTA_DG_OPEN_ST},
+/* CI_RX_WRITEBUF_EVT */ {BTA_DG_WRITEBUF, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* CI_CONTROL_EVT */ {BTA_DG_CONTROL, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* RFC_OPEN_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* RFC_CLOSE_EVT */ {BTA_DG_RFC_CLOSE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* RFC_TX_READY_EVT */ {BTA_DG_RX_PATH, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* RFC_RX_READY_EVT */ {BTA_DG_TX_PATH, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* RFC_FC_EVT */ {BTA_DG_RX_PATH, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* RFC_CONTROL_EVT */ {BTA_DG_RFC_CONTROL, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* DISC_RESULT_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* DISC_OK_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPEN_ST},
+/* DISC_FAIL_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_OPEN_ST}
+};
+
+/* state table for closing state */
+const UINT8 bta_dg_st_closing[][BTA_DG_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* API_CLOSE_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* API_SHUTDOWN_EVT */ {BTA_DG_DEL_RECORD, BTA_DG_SET_DEALLOC, BTA_DG_CLOSING_ST},
+/* API_LISTEN_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* API_OPEN_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* CI_TX_READY_EVT */ {BTA_DG_TX_PATH, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* CI_RX_READY_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* CI_TX_FLOW_EVT */ {BTA_DG_FC_STATE, BTA_DG_TX_PATH, BTA_DG_CLOSING_ST},
+/* CI_RX_WRITEBUF_EVT */ {BTA_DG_WRITEBUF, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* CI_CONTROL_EVT */ {BTA_DG_CONTROL, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* RFC_OPEN_EVT */ {BTA_DG_CLOSE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* RFC_CLOSE_EVT */ {BTA_DG_RFC_CLOSE, BTA_DG_IGNORE, BTA_DG_INIT_ST},
+/* RFC_TX_READY_EVT */ {BTA_DG_RX_PATH, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* RFC_RX_READY_EVT */ {BTA_DG_TX_PATH, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* RFC_FC_EVT */ {BTA_DG_RX_PATH, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* RFC_CONTROL_EVT */ {BTA_DG_RFC_CONTROL, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* DISC_RESULT_EVT */ {BTA_DG_FREE_DB, BTA_DG_RFC_CLOSE, BTA_DG_INIT_ST},
+/* DISC_OK_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST},
+/* DISC_FAIL_EVT */ {BTA_DG_IGNORE, BTA_DG_IGNORE, BTA_DG_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_DG_ST_TBL)[BTA_DG_NUM_COLS];
+
+/* state table */
+const tBTA_DG_ST_TBL bta_dg_st_tbl[] = {
+ bta_dg_st_init,
+ bta_dg_st_opening,
+ bta_dg_st_open,
+ bta_dg_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* DG control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_DG_CB bta_dg_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function bta_dg_scb_alloc
+**
+** Description Allocate a DG server control block.
+**
+**
+** Returns pointer to the scb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+static tBTA_DG_SCB *bta_dg_scb_alloc(void)
+{
+ tBTA_DG_SCB *p_scb = &bta_dg_cb.scb[0];
+ int i;
+
+ for (i = 0; i < BTA_DG_NUM_CONN; i++, p_scb++)
+ {
+ if (!p_scb->in_use)
+ {
+ p_scb->in_use = TRUE;
+ APPL_TRACE_DEBUG1("bta_dg_scb_alloc %d", bta_dg_scb_to_idx(p_scb));
+ break;
+ }
+ }
+
+ if (i == BTA_DG_NUM_CONN)
+ {
+ /* out of lcbs */
+ p_scb = NULL;
+ APPL_TRACE_WARNING0("Out of scbs");
+ }
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_sm_execute
+**
+** Description State machine event handling function for DG
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_sm_execute(tBTA_DG_SCB *p_scb, UINT16 event, tBTA_DG_DATA *p_data)
+{
+ tBTA_DG_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+ switch( event )
+ {
+ case BTA_DG_CI_TX_READY_EVT:
+ case BTA_DG_CI_RX_READY_EVT:
+ case BTA_DG_RFC_TX_READY_EVT:
+ case BTA_DG_RFC_RX_READY_EVT:
+ break;
+ default:
+ APPL_TRACE_EVENT3("DG scb=%d event=0x%x state=%d", bta_dg_scb_to_idx(p_scb), event, p_scb->state);
+ break;
+ }
+
+ /* look up the state table for the current state */
+ state_table = bta_dg_st_tbl[p_scb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_scb->state = state_table[event][BTA_DG_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_DG_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_DG_IGNORE)
+ {
+ (*bta_dg_action[action])(p_scb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_api_enable
+**
+** Description Handle an API enable event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dg_api_enable(tBTA_DG_DATA *p_data)
+{
+ /* initialize control block */
+ memset(&bta_dg_cb, 0, sizeof(bta_dg_cb));
+
+ /* store callback function */
+ bta_dg_cb.p_cback = p_data->api_enable.p_cback;
+
+ /* call callback with enable event */
+ (*bta_dg_cb.p_cback)(BTA_DG_ENABLE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_api_disable
+**
+** Description Handle an API disable event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dg_api_disable(tBTA_DG_DATA *p_data)
+{
+ /* close/shutdown all scbs in use */
+ tBTA_DG_SCB *p_scb = &bta_dg_cb.scb[0];
+ int i;
+ UINT16 event;
+
+ for (i = 0; i < BTA_DG_NUM_CONN; i++, p_scb++)
+ {
+ if (p_scb->in_use)
+ {
+ event = (p_scb->is_server) ? BTA_DG_API_SHUTDOWN_EVT : BTA_DG_API_CLOSE_EVT;
+ bta_dg_sm_execute(p_scb, event, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_new_conn
+**
+** Description Handle an API event that creates a new connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dg_new_conn(tBTA_DG_DATA *p_data)
+{
+ tBTA_DG_SCB *p_scb;
+
+ /* allocate an scb */
+ if ((p_scb = bta_dg_scb_alloc()) != NULL)
+ {
+ bta_dg_sm_execute(p_scb, p_data->hdr.event, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_rfc_port
+**
+** Description Handle a port event from RFCOMM. This function decodes
+** the port event mask into multiple state machine events.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dg_rfc_port(tBTA_DG_DATA *p_data)
+{
+ tBTA_DG_SCB *p_scb;
+
+ if ((p_scb = bta_dg_scb_by_handle(p_data->hdr.layer_specific)) != NULL)
+ {
+ if (p_data->rfc_port.code & PORT_EV_FC)
+ {
+ bta_dg_sm_execute(p_scb, BTA_DG_RFC_FC_EVT, p_data);
+ }
+
+ if (p_data->rfc_port.code & PORT_EV_TXEMPTY)
+ {
+ bta_dg_sm_execute(p_scb, BTA_DG_RFC_TX_READY_EVT, p_data);
+ }
+
+ if (p_data->rfc_port.code & PORT_EV_RXCHAR)
+ {
+ bta_dg_sm_execute(p_scb, BTA_DG_RFC_RX_READY_EVT, p_data);
+ }
+
+ if (p_data->rfc_port.code & (PORT_EV_CTS | PORT_EV_DSR | PORT_EV_RING))
+ {
+ bta_dg_sm_execute(p_scb, BTA_DG_RFC_CONTROL_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_scb_dealloc
+**
+** Description Deallocate a link control block.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dg_scb_dealloc(tBTA_DG_SCB *p_scb)
+{
+ APPL_TRACE_DEBUG1("bta_dg_scb_dealloc %d", bta_dg_scb_to_idx(p_scb));
+ if (p_scb->port_handle != 0)
+ {
+ bta_dg_cb.hdl_to_scb[p_scb->port_handle - 1] = 0;
+ }
+ memset(p_scb, 0, sizeof(tBTA_DG_SCB));
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_scb_to_idx
+**
+** Description Given a pointer to an scb, return its index.
+**
+**
+** Returns Index of scb.
+**
+*******************************************************************************/
+UINT8 bta_dg_scb_to_idx(tBTA_DG_SCB *p_scb)
+{
+ /* use array arithmetic to determine index */
+ return ((UINT8) (p_scb - bta_dg_cb.scb)) + 1;
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_scb_by_idx
+**
+** Description Given an scb index return pointer to scb.
+**
+**
+** Returns Pointer to scb or NULL if not allocated.
+**
+*******************************************************************************/
+tBTA_DG_SCB *bta_dg_scb_by_idx(UINT16 idx)
+{
+ tBTA_DG_SCB *p_scb;
+
+ /* verify index */
+ if (idx > 0 && idx <= BTA_DG_NUM_CONN)
+ {
+ p_scb = &bta_dg_cb.scb[idx - 1];
+ if (!p_scb->in_use)
+ {
+ p_scb = NULL;
+ APPL_TRACE_WARNING1("scb idx %d not allocated", idx);
+ }
+ }
+ else
+ {
+ p_scb = NULL;
+ APPL_TRACE_WARNING1("scb idx %d out of range", idx);
+ }
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_scb_by_handle
+**
+** Description Find scb associated with handle.
+**
+**
+** Returns Pointer to scb or NULL if not found.
+**
+*******************************************************************************/
+tBTA_DG_SCB *bta_dg_scb_by_handle(UINT16 handle)
+{
+ tBTA_DG_SCB *p_scb = NULL;
+
+ if (bta_dg_cb.hdl_to_scb[handle - 1] != 0)
+ {
+ p_scb = &bta_dg_cb.scb[bta_dg_cb.hdl_to_scb[handle - 1] - 1];
+ if (!p_scb->in_use)
+ {
+ p_scb = NULL;
+ }
+ }
+
+ if (p_scb == NULL)
+ {
+ APPL_TRACE_WARNING1("No scb for port handle %d", handle);
+ }
+
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_server_match
+**
+** Description Check if any servers exist with the same service name
+** and service id.
+**
+**
+** Returns Pointer to scb or NULL if not found.
+**
+*******************************************************************************/
+tBTA_DG_SCB *bta_dg_server_match(tBTA_DG_SCB *p_srv)
+{
+ tBTA_DG_SCB *p_scb = &bta_dg_cb.scb[0];
+ int i;
+
+ for (i = 0; i < BTA_DG_NUM_CONN; i++, p_scb++)
+ {
+ if (p_scb == p_srv)
+ {
+ continue;
+ }
+
+ if (p_scb->in_use && p_scb->is_server &&
+ (p_scb->service_id == p_srv->service_id) &&
+ (strcmp(p_srv->name, p_scb->name) == 0))
+ {
+ APPL_TRACE_DEBUG1("dg server match:%d", i);
+ return p_scb;
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_dg_hdl_event
+**
+** Description Data gateway main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_dg_hdl_event(BT_HDR *p_msg)
+{
+ tBTA_DG_SCB *p_scb;
+ BOOLEAN freebuf = TRUE;
+
+ switch (p_msg->event)
+ {
+ /* handle enable event */
+ case BTA_DG_API_ENABLE_EVT:
+ bta_dg_api_enable((tBTA_DG_DATA *) p_msg);
+ break;
+
+ /* handle disable event */
+ case BTA_DG_API_DISABLE_EVT:
+ bta_dg_api_disable((tBTA_DG_DATA *) p_msg);
+ break;
+
+ /* handle listen and open events */
+ case BTA_DG_API_LISTEN_EVT:
+ case BTA_DG_API_OPEN_EVT:
+ bta_dg_new_conn((tBTA_DG_DATA *) p_msg);
+ break;
+
+ /* handle RFCOMM port callback event mask */
+ case BTA_DG_RFC_PORT_EVT:
+ bta_dg_rfc_port((tBTA_DG_DATA *) p_msg);
+ break;
+
+ /* events that reference scb by index rather than port handle */
+ case BTA_DG_API_CLOSE_EVT:
+ case BTA_DG_API_SHUTDOWN_EVT:
+ case BTA_DG_DISC_RESULT_EVT:
+ if ((p_scb = bta_dg_scb_by_idx(p_msg->layer_specific)) != NULL)
+ {
+ bta_dg_sm_execute(p_scb, p_msg->event, (tBTA_DG_DATA *) p_msg);
+ }
+ break;
+
+ /* events that require buffer not be released */
+ case BTA_DG_CI_RX_WRITEBUF_EVT:
+ freebuf = FALSE;
+ /* fall through */
+
+ /* all others reference scb by port handle */
+ default:
+ if ((p_scb = bta_dg_scb_by_handle(p_msg->layer_specific)) != NULL)
+ {
+ bta_dg_sm_execute(p_scb, p_msg->event, (tBTA_DG_DATA *) p_msg);
+ }
+ break;
+ }
+ return freebuf;
+}
+#endif /* BTA_DG_INCLUDED */
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
new file mode 100644
index 0000000..e21dc3e
--- /dev/null
+++ b/bta/dm/bta_dm_act.c
@@ -0,0 +1,4678 @@
+/*****************************************************************************
+**
+** Name: bta_dm_act.c
+**
+** Description: This file contains the action functions for device manager
+** state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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(void);
+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 );
+
+#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
+
+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_FAX, /* BTA_FAX_SERVICE_ID */
+ UUID_SERVCLASS_LAN_ACCESS_USING_PPP, /* BTA_LAP_SERVICE_ID */
+ UUID_SERVCLASS_HEADSET, /* BTA_HSP_SERVICE_ID */
+ UUID_SERVCLASS_HF_HANDSFREE, /* BTA_HFP_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_HS_SERVICE_ID */
+ UUID_SERVCLASS_AG_HANDSFREE, /* BTA_HFP_HS_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_FAX, /* BTA_FAX_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
+
+};
+
+#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_ENABLE enable_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(&enable_event, 0, sizeof ( tBTA_DM_ENABLE ));
+ enable_event.status = BTA_FAILURE;
+ if( p_data->enable.p_sec_cback != NULL )
+ p_data->enable.p_sec_cback (BTA_DM_ENABLE_EVT, (tBTA_DM_SEC *)&enable_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 );
+
+ 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 )
+ {
+ /* make sure we unregister, so that we don't motified again if another module starts */
+ 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)
+ {
+ 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, 1000);
+ }
+ 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_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
+
+ 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) ||
+ (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)
+ {
+ bta_dm_search_cb.services_found |=
+ (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index-1));
+ }
+ }
+ }
+
+ 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);
+
+ /* 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;
+
+ //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);
+ printf("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;
+ /* 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_ENABLE enable_event;
+
+ BTM_GetLocalDeviceAddr(enable_event.bd_addr);
+ enable_event.status = BTA_SUCCESS;
+
+ if(bta_dm_cb.p_sec_cback)
+ bta_dm_cb.p_sec_cback(BTA_DM_ENABLE_EVT, (tBTA_DM_SEC *)&enable_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;
+
+#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 )
+ bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, (tBTA_DM_SEC *)&p_data->acl_change.busy_level);
+ 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, (tBTA_DM_SEC *)&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, (tBTA_DM_SEC *)&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;
+
+ 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, (tBTA_DM_SEC *)&conn);
+ }
+
+ bta_dm_adjust_roles();
+}
+
+/*******************************************************************************
+**
+** 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_SIG_STRENGTH result;
+
+ if(p_result->status == BTM_SUCCESS)
+ {
+
+ bdcpy(result.bd_addr, p_result->rem_bda);
+ result.mask = BTA_SIG_STRENGTH_RSSI_MASK;
+ result.rssi_value = p_result->rssi;
+ if( bta_dm_cb.p_sec_cback!= NULL )
+ bta_dm_cb.p_sec_cback(BTA_DM_SIG_STRENGTH_EVT, (tBTA_DM_SEC *)&result);
+
+ }
+}
+
+/*******************************************************************************
+**
+** 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_SIG_STRENGTH result;
+
+ if(p_result->status == BTM_SUCCESS)
+ {
+
+ bdcpy(result.bd_addr, p_result->rem_bda);
+ result.mask = BTA_SIG_STRENGTH_LINK_QUALITY_MASK;
+ result.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, (tBTA_DM_SEC *)&result);
+
+ }
+}
+
+/*******************************************************************************
+**
+** 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)
+ {
+ 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();
+
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_adjust_roles
+**
+** Description Adjust roles
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_dm_adjust_roles(void)
+{
+
+ 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))
+ {
+
+ BTM_SwitchRole (bta_dm_cb.device_list.peer_device[i].peer_bdaddr, HCI_ROLE_MASTER, NULL);
+
+ }
+
+ }
+ }
+
+
+ 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..97e4777
--- /dev/null
+++ b/bta/dm/bta_dm_api.c
@@ -0,0 +1,1602 @@
+/*****************************************************************************
+**
+** Name: bta_dm_api.c
+**
+** Description: This is the API implementation file for the BTA
+** device manager.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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)
+{
+
+ BOOLEAN device_ok_to_remove = TRUE;
+
+ GKI_sched_lock();
+
+ if (BTM_IsAclConnectionUp(bd_addr))
+ {
+ /* Don't allow deletion while connection is active */
+ device_ok_to_remove = FALSE;
+ }
+ else /* Ok to remove the device in application layer */
+ {
+ BTM_SecDeleteDevice(bd_addr);
+ }
+ GKI_sched_unlock();
+
+ if(device_ok_to_remove)
+ return BTA_SUCCESS;
+ else
+ return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** 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;
+ }
+#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 BSA).
+**
+** 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..e6a76af
--- /dev/null
+++ b/bta/dm/bta_dm_cfg.c
@@ -0,0 +1,424 @@
+/*****************************************************************************
+**
+** Name: bta_dm_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the device manager.
+**
+** Copyright (c) 2003-2011, Broadcom Corp, All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+
+#ifndef BTA_DM_COD
+
+/*
+ * major : COD_MAJOR_PHONE
+ * minor : COD_MINOR_SMART_PHONE
+ * svc : None, will be set as each profile registers
+ *
+ */
+
+#define BTA_DM_COD {0x40, BTM_COD_MAJOR_PHONE, BTM_COD_MINOR_SMART_PHONE}
+#endif
+
+
+#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 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..b003cbe
--- /dev/null
+++ b/bta/dm/bta_dm_ci.c
@@ -0,0 +1,106 @@
+/*****************************************************************************
+**
+** Name: bta_dm_ci.c
+**
+** Description: This is the API implementation file for the BTA
+** device manager.
+**
+** Copyright (c) 2003-2009, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..5f1da2a
--- /dev/null
+++ b/bta/dm/bta_dm_int.h
@@ -0,0 +1,956 @@
+/*****************************************************************************
+**
+** Name: bta_dm_int.h
+**
+** Description: This is the private interface file for the BTA device
+** manager.
+**
+** Copyright (c) 2003-2012, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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 */
+
+#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_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_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
+
+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;
+
+} 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;
+
+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_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..a3dd167
--- /dev/null
+++ b/bta/dm/bta_dm_main.c
@@ -0,0 +1,331 @@
+/*****************************************************************************
+**
+** Name: bta_dm_main.c
+**
+** Description: This is the main implementation file for the BTA
+** device manager.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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 */
+
+#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..eb0dfe4
--- /dev/null
+++ b/bta/dm/bta_dm_pm.c
@@ -0,0 +1,980 @@
+/*****************************************************************************
+**
+** Name: bta_dm_act.c
+**
+** Description: This file contains the action functions for device manager
+** state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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;
+
+ 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_WARNING1("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_WARNING1("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_WARNING2("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..7ad840a
--- /dev/null
+++ b/bta/dm/bta_dm_sco.c
@@ -0,0 +1,684 @@
+/*****************************************************************************
+**
+** Name: bta_dm_sco.c
+**
+** Description: 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.
+**
+** Original code took from BTW/CE.
+**
+** Copyright (c) 2003-2007, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..fc18863
--- /dev/null
+++ b/bta/fs/bta_fs_cfg.c
@@ -0,0 +1,38 @@
+/*****************************************************************************
+**
+** Name: bta_fs_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the BTA File System.
+**
+** Copyright (c) 2003-2008, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..d6e52b4
--- /dev/null
+++ b/bta/fs/bta_fs_ci.c
@@ -0,0 +1,268 @@
+/*****************************************************************************
+**
+** Name: bta_fs_ci.c
+**
+** Description: This is the implementation file for the file system
+** call-in functions.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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/ft/bta_ft_cfg.c b/bta/ft/bta_ft_cfg.c
new file mode 100644
index 0000000..89171e0
--- /dev/null
+++ b/bta/ft/bta_ft_cfg.c
@@ -0,0 +1,86 @@
+/*****************************************************************************
+**
+** Name: bta_ft_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the BTA File Transfer Client and Server.
+**
+** Copyright (c) 2003-2010, Broadcom Inc., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+#include "bta_ftc_int.h"
+
+/* Realm Character Set */
+#ifndef BTA_FTS_REALM_CHARSET
+#define BTA_FTS_REALM_CHARSET 0 /* ASCII */
+#endif
+
+/* Specifies whether or not client's user id is required during obex authentication */
+#ifndef BTA_FTS_USERID_REQ
+#define BTA_FTS_USERID_REQ FALSE
+#endif
+
+#ifndef BTA_FTC_AUTO_FILE_LIST
+#define BTA_FTC_AUTO_FILE_LIST TRUE
+#endif
+
+#ifndef BTA_FTC_ABORT_TIMEOUT
+#define BTA_FTC_ABORT_TIMEOUT 7000 /* 7 Secs for the low baud rates and SRM mode */
+#endif
+
+#ifndef BTA_FTC_STOP_TIMEOUT
+#define BTA_FTC_STOP_TIMEOUT 2000
+#endif
+
+#ifndef BTA_FTC_SUSPEND_TIMEOUT
+#define BTA_FTC_SUSPEND_TIMEOUT 10000
+#endif
+
+#ifndef BTA_FTC_PCE_SUPPORTED_FEAT /* mask: 1/download, 2/browsing */
+#define BTA_FTC_PCE_SUPPORTED_FEAT 0 /* 3/both, 0/PBAP PCE not supported */
+#endif
+
+#ifndef BTA_FTC_PCE_SERVICE_NAME
+#define BTA_FTC_PCE_SERVICE_NAME "PBAP PCE"
+#endif
+
+#ifndef BTA_FTC_2X_SUPPORTED
+#define BTA_FTC_2X_SUPPORTED TRUE
+#endif
+
+const tBTA_FT_CFG bta_ft_cfg =
+{
+#if (defined BIP_INCLUDED && BIP_INCLUDED == TRUE && defined BTA_BI_INCLUDED && BTA_BI_INCLUDED == TRUE)
+ bta_ftc_bi_action, /* Client only */
+#else
+ NULL, /* Client only */
+#endif
+
+ BTA_FTS_REALM_CHARSET, /* Server only */
+ BTA_FTS_USERID_REQ, /* Server only */
+ BTA_FTC_AUTO_FILE_LIST, /* Client only */
+ BTA_FTC_PCE_SUPPORTED_FEAT, /* Client only */
+ BTA_FTC_PCE_SERVICE_NAME, /* Client only */
+ BTA_FTC_ABORT_TIMEOUT, /* Client only */
+ BTA_FTC_STOP_TIMEOUT , /* Client only */
+ BTA_FTC_SUSPEND_TIMEOUT /* Client only - used for 2X only */
+#if BTA_FTC_2X_SUPPORTED == TRUE
+// btla-specific ++
+ , 0 // [no reliable sess] /* non-0 to allow reliable session (Server Only) */
+ , 0 // [no reliable sess] /* the maximum number of suspended session (Server Only) */
+// btla-specific --
+ , TRUE /* TRUE to use Obex Over L2CAP (Server Only) */
+ , TRUE /* TRUE to engage Single Response Mode (Server Only) */
+#else
+ , 0 /* non-0 to allow reliable session (Server Only) */
+ , 0 /* the maximum number of suspended session (Server Only) */
+ , FALSE /* TRUE to use Obex Over L2CAP (Server Only) */
+ , FALSE /* TRUE to engage Single Response Mode (Server Only) */
+#endif
+};
+
+tBTA_FT_CFG *p_bta_ft_cfg = (tBTA_FT_CFG *)&bta_ft_cfg;
+
diff --git a/bta/ft/bta_ftc_act.c b/bta/ft/bta_ftc_act.c
new file mode 100644
index 0000000..bdec2d3
--- /dev/null
+++ b/bta/ft/bta_ftc_act.c
@@ -0,0 +1,2062 @@
+/*****************************************************************************
+**
+** Name: bta_ftc_act.c
+**
+** Description: This file contains the file transfer action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_FT_INCLUDED) && (BTA_FT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bd.h"
+#include "port_api.h"
+#include "obx_api.h"
+#include "goep_util.h"
+#include "sdp_api.h"
+#include "bta_fs_api.h"
+#include "bta_ft_api.h"
+#include "bta_ftc_int.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#include "btm_api.h"
+#include "rfcdefs.h"
+#include "utl.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+/* sdp discovery database size */
+#define BTA_FTC_DISC_SIZE 400
+
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if BTA_FTC_DEBUG == TRUE
+static char *ftc_obx_evt_code(tOBX_EVENT evt_code);
+#endif
+
+static void ftc_reset_cb (tBTA_FTC_CB *p_cb);
+static void bta_ftc_sdp_cback(UINT16 status);
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_ftc_init_open
+**
+** Description Initiate a connection with a peer device's service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_init_open(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ p_cb->obx_oper = FTC_OP_NONE;
+ p_cb->sec_mask = p_data->api_open.sec_mask;
+ p_cb->services = p_data->api_open.services;
+ p_cb->srm = p_data->api_open.srm;
+ p_cb->nonce = p_data->api_open.nonce;
+ bdcpy(p_cb->bd_addr, p_data->api_open.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_abort
+**
+** Description Abort an active Get or Put operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_abort(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ /* Abort an active request */
+ if (p_cb->obx_oper != FTC_OP_NONE)
+ {
+ p_cb->aborting = FTC_ABORT_REQ_NOT_SENT;
+
+ /* Issue the abort request only if no request pending.
+ * some devices do not like out of sequence aborts even though
+ * the spec allows it */
+ if ( !p_cb->req_pending || p_cb->first_req_pkt ) /* allow request for the first packet */
+ {
+
+ p_cb->aborting = FTC_ABORT_REQ_SENT; /* protection agains sending AbortReq twice in
+ certain conditions */
+ OBX_AbortReq(p_cb->obx_handle, (BT_HDR *)NULL);
+ /* Start abort response timer */
+ p_cb->timer_oper = FTC_TIMER_OP_ABORT;
+ bta_sys_start_timer(&p_cb->rsp_timer, BTA_FTC_RSP_TOUT_EVT,
+ p_bta_ft_cfg->abort_tout);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_api_action
+**
+** Description Send an Action command to the connected server
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_api_action(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTC_STATUS status = BTA_FTC_FAIL;
+ tBTA_FTC_EVT event = BTA_FTC_COPY_EVT + p_data->api_action.action;
+
+ if (p_cb->obx_oper == FTC_OP_NONE)
+ {
+ /* TODO: we need to check the connected profile here */
+ p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, OBX_CMD_POOL_SIZE);
+ OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)p_data->api_action.p_src);
+ if (p_data->api_action.action == BTA_FT_ACT_PERMISSION)
+ {
+ OBX_AddPermissionHdr(p_obx->p_pkt, p_data->api_action.permission[0],
+ p_data->api_action.permission[1], p_data->api_action.permission[2]);
+ }
+ else
+ {
+ OBX_AddUtf8DestNameHdr(p_obx->p_pkt, (UINT8 *)p_data->api_action.p_dest);
+ }
+
+ if (OBX_ActionReq(p_cb->obx_handle, p_data->api_action.action, p_obx->p_pkt) == OBX_SUCCESS)
+ {
+ status = BTA_FTC_OK;
+ p_cb->req_pending = TRUE;
+ p_cb->obx_oper = FTC_OP_COPY + p_data->api_action.action;
+ p_obx->p_pkt = NULL; /* OBX will free the packet */
+ }
+ }
+
+ if (status != BTA_FTC_OK) /* Send an error response to the application */
+ {
+ utl_freebuf((void**)&p_obx->p_pkt);
+ p_cb->p_cback(event, (tBTA_FTC *)&status);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_action_rsp
+**
+** Description Process the response to an action command
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_action_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_FTC_STATUS status = BTA_FTC_FAIL;
+ tBTA_FTC_EVT event = BTA_FTC_COPY_EVT + p_cb->obx_oper - FTC_OP_COPY;
+
+ p_cb->req_pending = FALSE;
+
+ if (p_evt->rsp_code == OBX_RSP_OK)
+ status = BTA_FTC_OK;
+
+ APPL_TRACE_DEBUG2("bta_ftc_obx_action_rsp rsp_code:0x%x, status:%d", p_evt->rsp_code, status);
+ p_cb->obx_oper = FTC_OP_NONE;
+
+ utl_freebuf((void**)&p_evt->p_pkt); /* Done with Obex packet */
+ p_cb->p_cback(event, (tBTA_FTC *)&status);
+
+ /* If successful, initiate a directory listing */
+ if (event != BTA_FTC_PERMISSION_EVT &&
+ p_evt->rsp_code == OBX_RSP_OK && p_bta_ft_cfg->auto_file_list &&
+ (p_cb->sdp_service == UUID_SERVCLASS_OBEX_FILE_TRANSFER) )
+ {
+ bta_ftc_get_listing(p_cb, ".", NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_get_srm_rsp
+**
+** Description Process the response to an get command after suspend is sent
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_get_srm_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_ACTION p_act;
+ /* TODO remove
+ if (FTC_SUSPEND_REQ_NOT_SENT == p_cb->aborting)
+ {
+ p_cb->aborting = 0;
+ OBX_SessionReq (p_cb->obx_handle, OBX_SESS_OP_SUSPEND, 0);
+ p_cb->timer_oper = FTC_TIMER_OP_SUSPEND;
+ bta_sys_start_timer(&p_cb->rsp_timer, BTA_FTC_RSP_TOUT_EVT, p_bta_ft_cfg->suspend_tout );
+ }
+ */
+
+ if (p_cb->timer_oper == FTC_TIMER_OP_SUSPEND)
+ {
+ p_act = bta_ftc_obx_get_rsp;
+ }
+ else
+ p_act = bta_ftc_ignore_obx;
+ (p_act)(p_cb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_ci_write_srm
+**
+** Description Continue with the current write operation after suspend is sent
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_ci_write_srm(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ if (p_cb->timer_oper == FTC_TIMER_OP_SUSPEND)
+ {
+ bta_ftc_ci_write(p_cb, p_data);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ftc_init_putfile
+**
+** Description Push a file to the OPP or FTP server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_init_putfile(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FS_CO_STATUS status;
+ tBTA_FTC data;
+ BOOLEAN is_dir;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ data.status = BTA_FTC_FAIL;
+ if (p_cb->obx_oper == FTC_OP_NONE)
+ {
+ if (p_cb->sdp_service != UUID_SERVCLASS_PBAP_PSE)
+ {
+ p_cb->obx_oper = FTC_OP_PUT_FILE;
+
+ status = bta_fs_co_access(p_data->api_put.p_name, BTA_FS_ACC_READ,
+ &is_dir, p_cb->app_id);
+ /* Verify that the file exists, and get (optional) file length */
+ if (is_dir || status != BTA_FS_CO_OK)
+ {
+ /* Local file is not accessible or does not exist */
+ if (is_dir || status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+ else
+ {
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len+1, p_data->api_put.p_name, p_bta_fs_cfg->max_path_len);
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open(p_cb->p_name, BTA_FS_O_RDONLY, 0, BTA_FTC_CI_OPEN_EVT,
+ p_cb->app_id);
+ rsp_code = OBX_RSP_OK;
+ }
+ }
+ if (rsp_code != OBX_RSP_OK)
+ {
+ p_data->obx_evt.rsp_code = rsp_code;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ }
+ return;
+ }
+ else
+ {
+ /* PBAP does not allow PUT */
+ data.status = BTA_FTC_NO_PERMISSION;
+ }
+ }
+
+ p_cb->p_cback(BTA_FTC_PUTFILE_EVT, &data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_init_getfile
+**
+** Description Pull a file off the server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_init_getfile(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_API_GET *p_get = &p_data->api_get;
+ tBTA_FTC_GET_PARAM *p_param = p_get->p_param;
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTC_STATUS status = BTA_FTC_FAIL;
+ tBTA_FTC data;
+ UINT16 buflen;
+ UINT16 rem_name_len;
+ BOOLEAN is_ok;
+ UINT8 *p = (UINT8 *)BTA_FTC_PULL_VCARD_ENTRY_TYPE;
+ UINT8 *p_start;
+ UINT16 len = 0;
+
+ /* Available for FTP only */
+ if (p_cb->obx_oper == FTC_OP_NONE &&
+ (p_cb->sdp_service == UUID_SERVCLASS_OBEX_FILE_TRANSFER ||
+ p_cb->sdp_service == UUID_SERVCLASS_PBAP_PSE) )
+ {
+ p_cb->first_req_pkt = TRUE;
+ p_obx->offset = 0;
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, OBX_CMD_POOL_SIZE/*p_cb->peer_mtu*/)) != NULL)
+ {
+ /* Add the Name Header to the request */
+ is_ok = OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)p_get->p_rem_name);
+
+ if (p_cb->sdp_service == UUID_SERVCLASS_PBAP_PSE && is_ok)
+ {
+ /* add type header */
+ if (p_get->obj_type == BTA_FTC_GET_PB)
+ p = (UINT8 *)BTA_FTC_PULL_PB_TYPE;
+ is_ok = OBX_AddTypeHdr(p_obx->p_pkt, (char *)p);
+
+ /* add app params for PCE */
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ p = p_start;
+ if (p_get->obj_type != BTA_FTC_GET_PB || p_param->max_list_count != 0)
+ {
+ if (p_param->filter)
+ {
+ *p++ = BTA_FTC_APH_FILTER;
+ *p++ = 8;
+ /* set proprietary filter to 0 */
+ UINT32_TO_BE_STREAM(p, 0);
+ UINT32_TO_BE_STREAM(p, p_param->filter);
+ }
+ if (p_param->format < BTA_FTC_FORMAT_MAX)
+ {
+ *p++ = BTA_FTC_APH_FORMAT;
+ *p++ = 1;
+ *p++ = p_param->format;
+ }
+ }
+
+ if (p_get->obj_type == BTA_FTC_GET_PB)
+ {
+ /* this is mandatory */
+ *p++ = BTA_FTC_APH_MAX_LIST_COUNT;
+ *p++ = 2;
+ UINT16_TO_BE_STREAM(p, p_param->max_list_count);
+
+ if (p_param->list_start_offset)
+ {
+ *p++ = BTA_FTC_APH_LIST_STOFF;
+ *p++ = 2;
+ UINT16_TO_BE_STREAM(p, p_param->list_start_offset);
+ }
+ }
+
+ /* If any of the app param header is added */
+ if (p != p_start)
+ {
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+ }
+ }
+
+ rem_name_len = (UINT16)(strlen(p_get->p_rem_name) + 1);
+ /* Need a buffer that can hold the local path and UTF-8 filename */
+ buflen = p_bta_fs_cfg->max_path_len + 2 + rem_name_len;
+
+ /* Save the UNICODE name of the remote file, and local filename and path */
+ if ((p_cb->p_name = (char *)GKI_getbuf(buflen)) != NULL)
+ {
+ memset(p_cb->p_name, 0, buflen);
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len, p_get->p_name, p_bta_fs_cfg->max_path_len-1);
+
+ p_cb->obj_type = p_get->obj_type;
+ p_cb->obx_oper = FTC_OP_GET_FILE;
+ if (p_cb->obj_type == BTA_FTC_GET_PB && p_param->max_list_count == 0)
+ {
+ /* getting the phone book size only. do not need to open a file */
+ bta_ftc_send_get_req(p_cb);
+ }
+ else
+ {
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open(p_cb->p_name,
+ (BTA_FS_O_RDWR | BTA_FS_O_CREAT | BTA_FS_O_TRUNC),
+ 0, BTA_FTC_CI_OPEN_EVT, p_cb->app_id);
+ }
+ status = BTA_FTC_OK;
+ }
+ }
+
+ if (status != BTA_FTC_OK)
+ {
+ data.status = status;
+ p_cb->p_cback(BTA_FTC_GETFILE_EVT, &data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_chdir
+**
+** Description Change Directory and get a listing of it.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_chdir(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_API_CHDIR *p_chdir = &p_data->api_chdir;
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ tOBX_SETPATH_FLAG obx_flags = OBX_SPF_NO_CREATE;
+ tBTA_FTC_STATUS status = BTA_FTC_FAIL;
+ UINT16 len = OBX_CMD_POOL_SIZE; /* Don't need special OBX buffer pool */
+
+ /* Only process if no other OBX operation is active and connected to FTP */
+ if (p_cb->obx_oper == FTC_OP_NONE)
+ {
+ if (p_cb->sdp_service == UUID_SERVCLASS_OBEX_FILE_TRANSFER ||
+ p_cb->sdp_service == UUID_SERVCLASS_PBAP_PSE )
+ {
+ /* Allocate an OBX packet */
+ if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle, len)) != NULL)
+ {
+ status = BTA_FTC_OK;
+
+ /* Add the name header if not backing up */
+ if (p_chdir->flag != BTA_FTC_FLAG_BACKUP)
+ {
+ if (!OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)p_chdir->p_dir))
+ status = BTA_FTC_FAIL;
+ }
+ else
+ obx_flags |= OBX_SPF_BACKUP;
+ }
+ }
+ }
+
+ if (status == BTA_FTC_OK)
+ {
+ if (OBX_SetPathReq(p_cb->obx_handle, obx_flags, p_obx->p_pkt))
+ {
+ status = BTA_FTC_FAIL;
+ }
+ else
+ {
+ p_cb->req_pending = TRUE;
+ p_cb->obx_oper = FTC_OP_CHDIR;
+ p_obx->p_pkt = NULL; /* OBX will free the packet */
+ }
+
+ }
+
+ if (status != BTA_FTC_OK) /* Send an error response to the application */
+ {
+ utl_freebuf((void**)&p_obx->p_pkt);
+ p_cb->p_cback(BTA_FTC_CHDIR_EVT, (tBTA_FTC *)&status);
+ }
+}
+
+/*******************************************************************************
+**
+** Function ftp_clnt_listdir
+**
+** Description List the specified directory contents.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_listdir(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ /* Only process if no other OBX operation is active and connected to FTP */
+ if (p_cb->obx_oper == FTC_OP_NONE)
+ bta_ftc_get_listing(p_cb, p_data->api_list.p_dir, p_data->api_list.p_param);
+ else
+ bta_ftc_listing_err(&p_cb->obx.p_pkt, BTA_FTC_FAIL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_remove
+** Description Remove the specified directory or a file.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_remove(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTC_STATUS status = BTA_FTC_OK;
+
+ APPL_TRACE_DEBUG1("bta_ftc_remove status:%d", p_cb->obx_oper);
+
+ if (p_data->api_mkdir.p_dir[0] != '\0')
+ {
+
+ /* Only process if no other OBX operation is active and connected to FTP */
+ if (p_cb->obx_oper == FTC_OP_NONE)
+ {
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, OBX_CMD_POOL_SIZE)) != NULL)
+ {
+ /* Add the Name Header to the request */
+ status = BTA_FTC_OK;
+ OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)p_data->api_remove.p_name);
+ }
+ else
+ status = BTA_FTC_FAIL;
+ }
+ else
+ status = BTA_FTC_BUSY;
+ }
+ else
+ status = BTA_FTC_NOT_FOUND;
+
+ if (status == BTA_FTC_OK)
+ {
+ if ((OBX_PutReq(p_cb->obx_handle, TRUE, p_obx->p_pkt)) == OBX_SUCCESS)
+ {
+ p_cb->req_pending = TRUE;
+ p_cb->obx_oper = FTC_OP_DELETE;
+ p_obx->p_pkt = NULL; /* OBX will free the packet */
+ }
+ else
+ status = BTA_FTC_FAIL;
+ }
+
+ if (status != BTA_FTC_OK) /* Send an error response to the application */
+ {
+ utl_freebuf((void**)&p_obx->p_pkt);
+ p_cb->p_cback(BTA_FTC_REMOVE_EVT, (tBTA_FTC *)&status);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_ftc_mkdir
+**
+** Description Create the specified directory.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_mkdir(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTC_STATUS status = BTA_FTC_OK;
+
+ if (p_data->api_mkdir.p_dir[0] != '\0')
+ {
+ /* Only process if no other OBX operation is active and connected to FTP */
+ if (p_cb->obx_oper == FTC_OP_NONE)
+ {
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, OBX_CMD_POOL_SIZE)) != NULL)
+ {
+ /* Add the Name Header to the request */
+ status = BTA_FTC_OK;
+ OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)p_data->api_mkdir.p_dir);
+ }
+ }
+ else
+ status = BTA_FTC_BUSY;
+ }
+ else
+ status = BTA_FTC_NOT_FOUND;
+
+ if (status == BTA_FTC_OK )
+ {
+ if ((OBX_SetPathReq(p_cb->obx_handle, 0, p_obx->p_pkt)) == OBX_SUCCESS)
+ {
+ p_cb->req_pending = TRUE;
+ p_cb->obx_oper = FTC_OP_MKDIR;
+ p_obx->p_pkt = NULL; /* OBX will free the packet */
+ }
+ else
+ status = BTA_FTC_FAIL;
+ }
+
+ if (status != BTA_FTC_OK) /* Send an error response to the application */
+ {
+ utl_freebuf((void**)&p_obx->p_pkt);
+ p_cb->p_cback(BTA_FTC_MKDIR_EVT, (tBTA_FTC *)&status);
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_ftc_send_authrsp
+**
+** Description Pass the response to an authentication request back to the
+** client.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_send_authrsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ UINT8 *p_pwd = NULL;
+ UINT8 *p_userid = NULL;
+
+ if (p_bta_ft_cfg->p_bi_action != NULL &&
+ p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_AUTHRSP_IDX] &&
+ p_cb->sdp_service == UUID_SERVCLASS_IMAGING_RESPONDER)
+ {
+ (p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_AUTHRSP_IDX])(p_cb, p_data);
+ return;
+ }
+ else
+ {
+ if (p_data->auth_rsp.key_len > 0)
+ p_pwd = (UINT8 *)p_data->auth_rsp.key;
+ if (p_data->auth_rsp.userid_len > 0)
+ p_userid = (UINT8 *)p_data->auth_rsp.userid;
+
+ OBX_AuthResponse(p_cb->obx_handle, p_pwd, p_data->auth_rsp.key_len,
+ p_userid, p_data->auth_rsp.userid_len, FALSE);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_trans_cmpl
+**
+** Description push/pull complete
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_trans_cmpl(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC param;
+
+ /* Close the opened file */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+ }
+
+ param.status = bta_ftc_convert_obx_to_ftc_status(p_data->obx_evt.rsp_code);
+
+ if (p_cb->obx_oper == FTC_OP_PUT_FILE)
+ p_cb->p_cback(BTA_FTC_PUTFILE_EVT, &param);
+ else if (p_cb->obx_oper == FTC_OP_GET_FILE)
+ {
+ if (param.status != BTA_FTC_OK)
+ {
+ bta_fs_co_unlink(p_cb->p_name, p_cb->app_id);
+ APPL_TRACE_WARNING2("FTC: Get File Operation Aborted or Error [%s], status 0x%02x",
+ p_cb->p_name, param.status);
+ }
+
+ p_cb->p_cback(BTA_FTC_GETFILE_EVT, &param);
+ }
+
+ /* Clean up control block */
+ ftc_reset_cb(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_ci_write
+**
+** Description Continue with the current write operation
+** (Get File processing)
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_ci_write(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTC param;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ p_cb->cout_active = FALSE;
+
+ /* Process write call-in event if operation is still active */
+ if (p_cb->obx_oper != FTC_OP_GET_FILE)
+ return;
+
+ /* Free current packet */
+ utl_freebuf((void**)&p_obx->p_pkt);
+
+ /* Process any pending abort */
+ if (p_cb->aborting)
+ {
+ p_cb->aborting |= FTC_ABORT_COUT_DONE;
+
+ /* If already have response to abort then notify appl and cleanup */
+ if (FTC_ABORT_COMPLETED == p_cb->aborting)
+ {
+ /* APPL_TRACE_DEBUG0("Received WRITE CALL-IN function; continuing abort..."); */
+
+ /* OBX_RSP_GONE indicates aborted; used internally when called from API */
+ p_data->obx_evt.rsp_code = (!p_cb->int_abort) ? OBX_RSP_GONE : OBX_RSP_INTRNL_SRVR_ERR;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ return;
+ }
+ }
+
+ if (p_data->write_evt.status == BTA_FS_CO_OK)
+ {
+ param.prog.bytes = p_obx->offset;
+ param.prog.file_size = p_cb->file_size;
+ p_cb->p_cback(BTA_FTC_PROGRESS_EVT, &param);
+
+ /* Send another Get request if not finished */
+ if (!p_obx->final_pkt)
+ {
+ /* send a new request */
+ bta_ftc_send_get_req(p_cb);
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ else
+ rsp_code = OBX_RSP_OK;
+ }
+
+ if (rsp_code != OBX_RSP_CONTINUE)
+ {
+ p_data->obx_evt.rsp_code = rsp_code;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_ci_read
+**
+** Description Handles the response to a read call-out request.
+** This is called within the OBX get file request. The
+** operation has completed, send the OBX packet out.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_ci_read(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FS_CI_READ_EVT *p_revt = &p_data->read_evt;
+ tBTA_FTC param;
+ BOOLEAN is_final;
+
+ p_cb->cout_active = FALSE;
+
+ /* Process read call-in event if operation is still active */
+ if (p_cb->obx_oper == FTC_OP_PUT_FILE)
+ {
+ if (!p_cb->aborting)
+ {
+ if (p_revt->status != BTA_FS_CO_OK && p_revt->status != BTA_FS_CO_EOF)
+ {
+ p_cb->int_abort = TRUE;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_API_ABORT_EVT, p_data);
+ }
+ else
+ {
+ is_final = (p_revt->status == BTA_FS_CO_EOF) ? TRUE: FALSE;
+
+ /* Add the body header to the packet */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_revt->num_read, is_final);
+
+ p_cb->obx.bytes_left -= p_revt->num_read;
+ p_cb->obx.offset += p_revt->num_read;
+
+ /* Send out the data */
+ OBX_PutReq(p_cb->obx_handle, is_final, p_obx->p_pkt);
+ p_obx->p_pkt = NULL;
+ p_cb->req_pending = TRUE;
+
+ /* Give application the status */
+ param.prog.bytes = p_revt->num_read;
+ param.prog.file_size = p_cb->file_size;
+ p_cb->p_cback(BTA_FTC_PROGRESS_EVT, &param);
+ }
+ }
+ else
+ {
+ /* Process any pending abort */
+ p_cb->aborting |= FTC_ABORT_COUT_DONE;
+
+ /* If already have response to abort then notify appl and cleanup */
+ if (FTC_ABORT_COMPLETED == p_cb->aborting)
+ {
+ /* APPL_TRACE_DEBUG0("Received READ CALL-IN function; continuing abort..."); */
+
+ /* OBX_RSP_GONE indicates aborted; used internally when called from API */
+ p_data->obx_evt.rsp_code = (!p_cb->int_abort) ? OBX_RSP_GONE : OBX_RSP_INTRNL_SRVR_ERR;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ return;
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_ci_open
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_ci_open(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FS_CI_OPEN_EVT *p_open = &p_data->open_evt;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ p_cb->cout_active = FALSE;
+ APPL_TRACE_DEBUG2("bta_ftc_ci_open status:%d, aborting:%d", p_open->status, p_cb->aborting);
+
+ /* Process any pending abort */
+ if (p_cb->aborting)
+ {
+ p_cb->aborting |= FTC_ABORT_COUT_DONE;
+
+ /* If already have response to abort then notify appl and cleanup */
+ if (FTC_ABORT_COMPLETED == p_cb->aborting)
+ {
+ /* APPL_TRACE_DEBUG0("Received OPEN CALL-IN function; continuing abort..."); */
+
+ /* OBX_RSP_GONE indicates aborted; used internally when called from API */
+ p_data->obx_evt.rsp_code = (!p_cb->int_abort) ? OBX_RSP_GONE : OBX_RSP_INTRNL_SRVR_ERR;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ return;
+ }
+ }
+
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->fd = p_open->fd;
+
+ /* If using OBEX 1.5 */
+ if (p_open->p_file)
+ {
+ if ((p_cb->p_name != NULL) ||
+ (p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ /* save the image file name */
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len+1, p_open->p_file, p_bta_fs_cfg->max_path_len);
+ p_cb->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ p_cb->first_req_pkt = FALSE;
+ }
+ }
+ else
+ p_cb->first_req_pkt = TRUE;
+
+ APPL_TRACE_DEBUG2("first_req_pkt:%d obx_oper:%d", p_cb->first_req_pkt, p_cb->obx_oper);
+
+ if (p_cb->obx_oper == FTC_OP_PUT_FILE)
+ {
+ p_cb->file_size = p_open->file_size;
+ rsp_code = bta_ftc_cont_put_file(p_cb, p_cb->first_req_pkt);
+ }
+ else if (p_cb->obx_oper == FTC_OP_GET_FILE)
+ {
+ /* Initiate the first OBX GET request */
+ rsp_code = bta_ftc_send_get_req(p_cb);
+ }
+ }
+ else
+ {
+ /* If using OBEX 1.5 */
+ if (p_open->status == BTA_FS_CO_NONE)
+ {
+ rsp_code = OBX_RSP_OK;
+ if (p_cb->obx_oper == FTC_OP_GET_LIST)
+ {
+ bta_ftc_abort(p_cb, NULL);
+ }
+ }
+ else
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else /* File could not be found */
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+ }
+
+ if (rsp_code != OBX_RSP_OK)
+ {
+ p_data->obx_evt.rsp_code = rsp_code;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_ci_resume
+**
+** Description Continue with the resume session
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_ci_resume(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FS_CI_RESUME_EVT *p_resume = &p_data->resume_evt;
+
+ APPL_TRACE_DEBUG3("bta_ftc_ci_resume status:%d, ssn:%d, info:%d",
+ p_resume->status, p_resume->ssn, p_resume->info);
+
+ if (p_resume->status == BTA_FS_CO_OK &&
+ OBX_AllocSession (p_resume->p_sess_info, 0, &p_cb->psm,
+ bta_ftc_obx_cback, &p_cb->obx_handle) == OBX_SUCCESS)
+ {
+ BTM_SetSecurityLevel (TRUE, "BTA_FTC", BTM_SEC_SERVICE_OBEX_FTP,
+ p_cb->sec_mask, p_cb->psm,
+ 0, 0);
+ OBX_ResumeSession (p_cb->bd_addr, p_resume->ssn, p_resume->offset, p_cb->obx_handle);
+ }
+ else
+ {
+ p_cb->status = BTA_FTC_OBX_ERR;
+ p_data->obx_evt.rsp_code = OBX_RSP_FAILED;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CLOSE_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_conn_rsp
+**
+** Description Process the OBX connect event.
+** If FTP service, get directory listing.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_conn_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_FTC param;
+ tOBX_SESS_EVT *p_sess;
+ UINT8 obx_oper, *p_obx_oper = &p_cb->obx_oper;
+
+ APPL_TRACE_DEBUG1("bta_ftc_obx_conn_rsp obx_event=%d", p_evt->obx_event);
+
+ /* If using OBEX 1.5 */
+ if (p_evt->obx_event == OBX_SESSION_RSP_EVT)
+ {
+ p_sess = &p_evt->param.sess;
+ APPL_TRACE_DEBUG2("bta_ftc_obx_conn_rsp sess_id:0x%x/0x%x", p_cb->p_sess_info, p_sess->p_sess_info);
+ p_cb->p_sess_info = p_sess->p_sess_info;
+ APPL_TRACE_DEBUG2("client cb p_sess_info:0x%x obj_offset:x%x", p_cb->p_sess_info, p_sess->obj_offset);
+ if (p_cb->nonce != BTA_FTC_RESUME_NONCE)
+ {
+ p_obx_oper = &obx_oper;
+ p_cb->obx_oper = FTC_OP_NONE;
+ }
+ bta_fs_co_session_info(p_cb->bd_addr, p_cb->p_sess_info, p_sess->ssn, BTA_FS_CO_SESS_ST_ACTIVE, NULL, p_obx_oper, p_cb->app_id);
+ if ((p_sess->sess_op == OBX_SESS_OP_CREATE) || (p_sess->sess_op == OBX_SESS_OP_RESUME))
+ {
+ p_cb->state = BTA_FTC_W4_CONN_ST;
+ }
+ if (p_cb->obx_oper)
+ bta_fs_co_resume_op(p_sess->obj_offset, BTA_FTC_CI_OPEN_EVT, p_cb->app_id);
+ return;
+ }
+
+ p_cb->peer_mtu = p_data->obx_evt.param.conn.mtu;
+
+ APPL_TRACE_DEBUG2("bta_ftc_obx_conn_rsp peer_mtu=%d obx_oper:0x%x", p_cb->peer_mtu, p_cb->obx_oper);
+
+ /* OPP is connected and ready */
+ if (p_cb->sdp_service == UUID_SERVCLASS_OBEX_OBJECT_PUSH)
+ {
+ param.open.service = BTA_OPP_SERVICE_ID;
+ APPL_TRACE_EVENT0("[BTA FTC]OPP Service Id ");
+ }
+ /* PBAP is connected and ready */
+ else if (p_cb->sdp_service == UUID_SERVCLASS_PBAP_PSE)
+ {
+ param.open.service = BTA_PBAP_SERVICE_ID;
+ APPL_TRACE_EVENT0("[BTA FTC]PBAP Service Id ");
+ }
+ else /* Initiate directory listing if FTP service */
+ {
+ APPL_TRACE_EVENT0("[BTA FTC]FTP Service Id ");
+ param.open.service = BTA_FTP_SERVICE_ID;
+ if (p_bta_ft_cfg->auto_file_list && !p_cb->obx_oper)
+ {
+ bta_ftc_get_listing(p_cb, ".", NULL);
+ }
+ }
+
+ if (p_cb->p_sess_info == NULL)
+ {
+ bta_fs_co_session_info(p_cb->bd_addr, p_cb->p_sess_info, 0, BTA_FS_CO_SESS_ST_NONE, NULL, NULL, p_cb->app_id);
+ }
+ p_cb->suspending = FALSE;
+
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_FTC ,p_cb->app_id, p_cb->bd_addr);
+
+ param.open.version = p_cb->version;
+ p_cb->p_cback(BTA_FTC_OPEN_EVT, &param);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_sess_rsp
+**
+** Description Process the OBX session event.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_sess_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tOBX_SESS_EVT *p_sess = &p_data->obx_evt.param.sess;
+
+ APPL_TRACE_DEBUG3("bta_ftc_obx_sess_rsp obx_event=%d sess_op:%d, ssn:%d",
+ p_evt->obx_event, p_sess->sess_op, p_sess->ssn);
+ if (p_evt->obx_event == OBX_SESSION_RSP_EVT && p_sess->sess_op == OBX_SESS_OP_SUSPEND)
+ {
+ p_cb->p_sess_info = p_sess->p_sess_info;
+ APPL_TRACE_DEBUG1("client cb p_sess_info:0x%x", p_cb->p_sess_info);
+ bta_fs_co_suspend(p_cb->bd_addr, p_cb->p_sess_info, p_sess->ssn, &p_sess->timeout, NULL, p_cb->obx_oper, p_cb->app_id);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_suspended
+**
+** Description Process transport down suspend.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_suspended(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tOBX_SESS_EVT *p_sess = &p_data->obx_evt.param.sess;
+ UINT32 offset = 0;
+
+ APPL_TRACE_DEBUG4("bta_ftc_suspended obx_event=%d sess_op:%d, ssn:%d, obx_oper:%d",
+ p_evt->obx_event, p_sess->sess_op, p_sess->ssn, p_cb->obx_oper);
+ if (p_evt->obx_event == OBX_SESSION_INFO_EVT)
+ {
+ if ((p_cb->obx_oper != FTC_OP_GET_FILE) && (p_cb->obx_oper != FTC_OP_PUT_FILE) && (p_cb->obx_oper != FTC_OP_GET_LIST))
+ {
+ /* the other obx ops are single transaction.
+ * If the link is dropped before the transaction ends, re-transmit the request when the session resumes */
+ p_sess->ssn--;
+ p_cb->obx_oper = FTC_OP_NONE;
+ }
+ p_cb->suspending = TRUE;
+ bta_fs_co_suspend(p_cb->bd_addr, p_sess->p_sess_info, p_sess->ssn,
+ &p_sess->timeout, &offset, p_cb->obx_oper, p_cb->app_id);
+ /* do not need to worry about active call-out here.
+ * this is a result of OBX_SESSION_INFO_EVT
+ * OBX would report OBX_CLOSE_IND_EVT, which will eventually call bta_ftc_close_complete */
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_abort_rsp
+**
+** Description Process the OBX abort event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_abort_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ bta_sys_stop_timer(&p_cb->rsp_timer);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+
+ if (p_cb->obx_oper != FTC_OP_NONE)
+ {
+ if (!p_cb->cout_active)
+ {
+ /* OBX_RSP_GONE indicates aborted; used internally when called from API */
+ p_data->obx_evt.rsp_code = (!p_cb->int_abort) ? OBX_RSP_GONE : OBX_RSP_INTRNL_SRVR_ERR;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ }
+ else /* must wait for cout function to complete before finishing the abort */
+ {
+ /* Mark the fact we have already received the response from the peer */
+ p_cb->aborting |= FTC_ABORT_RSP_RCVD;
+ /* APPL_TRACE_DEBUG1("ftc_obx_abort_rsp()->Rcvd abort_rsp; waiting for callin...",
+ p_cb->aborting); */
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_password
+**
+** Description Process the OBX password request
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_password(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_FTC_AUTH parms;
+ tOBX_AUTH_OPT options;
+
+ memset(&parms, 0, sizeof(tBTA_FTC_AUTH));
+
+ /* Extract user id from packet (if available) */
+ if (OBX_ReadChallenge(p_evt->p_pkt, &parms.realm_charset,
+ &parms.p_realm,
+ &parms.realm_len, &options))
+ {
+ if (options & OBX_AO_USR_ID)
+ parms.userid_required = TRUE;
+ }
+
+ /* Don't need OBX packet any longer */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ /* Notify application */
+ p_cb->p_cback(BTA_FTC_AUTH_EVT, (tBTA_FTC *)&parms);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_timeout
+**
+** Description Process the OBX timeout event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_timeout(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+
+ /* If currently processing OBX request, peer is unresponsive so we're done */
+ if (p_cb->aborting || p_cb->obx_oper != FTC_OP_NONE)
+ {
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ if (p_cb->bic_handle != BTA_BIC_INVALID_HANDLE)
+ {
+ BTA_BicDeRegister(p_cb->bic_handle);
+ p_cb->bic_handle = BTA_BIC_INVALID_HANDLE;
+ }
+ else
+#endif
+ {
+ p_data->obx_evt.rsp_code = OBX_RSP_GONE;
+ p_cb->status = BTA_FTC_OBX_TOUT;
+
+ /* Start stop response timer */
+ p_cb->timer_oper = FTC_TIMER_OP_STOP;
+ bta_sys_start_timer(&p_cb->rsp_timer, BTA_FTC_RSP_TOUT_EVT,
+ p_bta_ft_cfg->stop_tout);
+
+ OBX_DisconnectReq(p_cb->obx_handle, NULL);
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CLOSE_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_put_rsp
+**
+** Description Process the OBX file put and delete file/folder events
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_put_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_FTC_STATUS status;
+
+ p_cb->req_pending = FALSE;
+ p_cb->first_req_pkt = FALSE;
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (p_cb->obx_oper == FTC_OP_PUT_FILE)
+ {
+ /* If not finished with Put, start another read */
+ if (p_evt->rsp_code == OBX_RSP_CONTINUE)
+ bta_ftc_cont_put_file(p_cb, FALSE);
+ else
+ {
+ p_data->obx_evt.rsp_code = p_evt->rsp_code;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ }
+ }
+
+ else if (p_cb->obx_oper == FTC_OP_DELETE)
+ {
+ status = bta_ftc_convert_obx_to_ftc_status(p_data->obx_evt.rsp_code);
+ p_cb->obx_oper = FTC_OP_NONE;
+ p_cb->p_cback(BTA_FTC_REMOVE_EVT, (tBTA_FTC *)&status);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_get_rsp
+**
+** Description Process the OBX file get and folder listing events
+** If the type header is not folder listing, then pulling a file.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_get_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+
+ APPL_TRACE_DEBUG2("bta_ftc_obx_get_rsp req_pending=%d obx_oper:%d", p_cb->req_pending, p_cb->obx_oper);
+ p_cb->req_pending = FALSE;
+
+ if (p_cb->obx_oper == FTC_OP_GET_FILE)
+ bta_ftc_proc_get_rsp(p_cb, p_data);
+ else if (p_cb->obx_oper == FTC_OP_GET_LIST)
+ bta_ftc_proc_list_data(p_cb, p_evt);
+ else /* Release the unexpected OBX response packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_obx_setpath_rsp
+**
+** Description Process the response to a change or make directory requests
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_setpath_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_FTC_STATUS status = BTA_FTC_FAIL;
+ tBTA_FTC_EVT event = BTA_FTC_CHDIR_EVT;
+
+ p_cb->req_pending = FALSE;
+
+ if (p_cb->obx_oper == FTC_OP_MKDIR)
+ event = BTA_FTC_MKDIR_EVT;
+
+ if (p_evt->rsp_code == OBX_RSP_OK)
+ status = BTA_FTC_OK;
+
+ p_cb->obx_oper = FTC_OP_NONE;
+
+ utl_freebuf((void**)&p_evt->p_pkt); /* Done with Obex packet */
+ p_cb->p_cback(event, (tBTA_FTC *)&status);
+
+ /* If successful, initiate a directory listing */
+ if (p_evt->rsp_code == OBX_RSP_OK && p_bta_ft_cfg->auto_file_list &&
+ (p_cb->sdp_service == UUID_SERVCLASS_OBEX_FILE_TRANSFER))
+ {
+ bta_ftc_get_listing(p_cb, ".", NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_rsp_timeout
+**
+** Description Process the OBX response timeout event
+** stop and abort
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_rsp_timeout(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ p_cb->timer_oper = FTC_TIMER_OP_STOP;
+ if (p_cb->timer_oper == FTC_TIMER_OP_ABORT)
+ {
+ /* Start stop response timer */
+ p_cb->status = BTA_FTC_ABORTED;
+ bta_sys_start_timer(&p_cb->rsp_timer, BTA_FTC_RSP_TOUT_EVT,
+ p_bta_ft_cfg->stop_tout);
+
+ OBX_DisconnectReq(p_cb->obx_handle, NULL);
+ }
+ else /* Timeout waiting for disconnect response */
+ {
+ p_cb->cout_active = FALSE;
+ bta_ftc_initialize(p_cb, p_data);
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ BTA_BicFreeXmlData(BTA_BIC_CAPABILITIES_EVT, (tBTA_BI_XML **)&p_cb->p_caps);
+#endif
+ /* force OBX to close port */
+ OBX_DisconnectReq(p_cb->obx_handle, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_initialize
+**
+** Description Initialize the control block.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_initialize(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FS_CO_STATUS status;
+
+ bta_sys_stop_timer(&p_cb->rsp_timer);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Delete an aborted unfinished get file operation */
+ if (p_cb->obx_oper == FTC_OP_GET_FILE && p_cb->suspending == FALSE)
+ {
+ status = bta_fs_co_unlink(p_cb->p_name, p_cb->app_id);
+ APPL_TRACE_WARNING2("FTC: Remove ABORTED Get File Operation [%s], status 0x%02x",
+ p_cb->p_name, status);
+ }
+ }
+
+ /* Clean up control block */
+ ftc_reset_cb(p_cb);
+ p_cb->sdp_service = 0;
+ p_cb->sdp_pending = FALSE;
+ p_cb->suspending = FALSE;
+ p_cb->p_sess_info = NULL;
+
+ if (p_cb->disabling)
+ {
+ if (p_cb->sdp_handle)
+ {
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ p_cb->sdp_handle = 0;
+ bta_sys_remove_uuid( UUID_SERVCLASS_PBAP_PCE );
+ }
+ p_cb->is_enabled = FALSE;
+ p_cb->disabling = FALSE;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_DISABLE_CMPL_EVT, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_stop_client
+**
+** Description Stop OBX client.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_stop_client(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ INT32 timeout;
+
+ APPL_TRACE_DEBUG1("bta_ftc_stop_client suspend:%d", p_data->api_close.suspend);
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ if (p_bta_ft_cfg->p_bi_action &&
+ p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_DEREGISTER_IDX] &&
+ p_cb->bic_handle != BTA_BIC_INVALID_HANDLE)
+ {
+ (p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_DEREGISTER_IDX])(p_cb, p_data);
+ }
+ else if (!p_cb->sdp_pending)
+#else
+ if (!p_cb->sdp_pending)
+#endif
+ {
+ if (p_data->api_close.suspend)
+ {
+ timeout = p_bta_ft_cfg->suspend_tout;
+ p_cb->timer_oper = FTC_TIMER_OP_SUSPEND;
+ p_cb->suspending = TRUE;
+ OBX_SessionReq (p_cb->obx_handle, OBX_SESS_OP_SUSPEND, 0);
+ p_cb->state = BTA_FTC_SUSPENDING_ST;
+
+ }
+ else
+ {
+ bta_fs_co_session_info(p_cb->bd_addr, p_cb->p_sess_info, 0, BTA_FS_CO_SESS_ST_NONE, NULL, NULL, p_cb->app_id);
+
+ timeout = p_bta_ft_cfg->stop_tout;
+ p_cb->timer_oper = FTC_TIMER_OP_STOP;
+ OBX_DisconnectReq(p_cb->obx_handle, NULL);
+ }
+ /* Start stop response timer */
+ bta_sys_start_timer(&p_cb->rsp_timer, BTA_FTC_RSP_TOUT_EVT, timeout );
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_close
+**
+** Description If not waiting for a call-in function, complete the closing
+** of the channel.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_close(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->sdp_pending && !p_cb->cout_active)
+ bta_ftc_sm_execute(p_cb, BTA_FTC_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_close
+**
+** Description If not waiting for a call-in function, complete the closing
+** of the channel.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_open_fail(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ bta_ftc_close(p_cb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_start_client
+**
+** Description Start an FTP or OPP client.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_start_client(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tOBX_STATUS status;
+ UINT16 mtu = OBX_MAX_MTU;
+ BOOLEAN srm = p_cb->srm;
+ UINT32 nonce = p_cb->nonce;
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+
+ p_cb->status = BTA_FTC_OK;
+ p_cb->p_sess_info = NULL;
+
+ if ( p_bta_ft_cfg->p_bi_action &&
+ p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_REGISTER_IDX] &&
+ p_cb->sdp_service == UUID_SERVCLASS_IMAGING_RESPONDER)
+ {
+ (p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_REGISTER_IDX])(p_cb, p_data);
+ return;
+ }
+
+ /* If using OBEX 1.5 */
+ if (p_cb->nonce == BTA_FTC_RESUME_NONCE)
+ {
+ APPL_TRACE_DEBUG1("bta_ftc_start_client psm:0x%x", p_data->sdp_ok.psm);
+ p_cb->psm = p_data->sdp_ok.psm;
+ bta_fs_co_resume (BTA_FTC_CI_SESSION_EVT, p_cb->app_id);
+ }
+ /* Allocate an OBX packet */
+ else
+ {
+ if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(OBX_HANDLE_NULL, OBX_CMD_POOL_SIZE)) != NULL)
+ {
+ p_cb->version = p_data->sdp_ok.version;
+
+ /* Add the target header if connecting to FTP service */
+ if (p_cb->sdp_service == UUID_SERVCLASS_OBEX_FILE_TRANSFER)
+ {
+ OBX_AddTargetHdr(p_obx->p_pkt, (UINT8 *)BTA_FTC_FOLDER_BROWSING_TARGET_UUID,
+ BTA_FTC_UUID_LENGTH);
+ }
+ /* Add the target header if connecting to PBAP service */
+ else if (p_cb->sdp_service == UUID_SERVCLASS_PBAP_PSE)
+ {
+ OBX_AddTargetHdr(p_obx->p_pkt, (UINT8 *)BTA_FTC_PB_ACCESS_TARGET_UUID,
+ BTA_FTC_UUID_LENGTH);
+ }
+
+ status = OBX_AllocSession (NULL, p_data->sdp_ok.scn, &p_data->sdp_ok.psm,
+ bta_ftc_obx_cback, &p_cb->obx_handle);
+
+ /* set security level */
+ if (p_data->sdp_ok.scn)
+ {
+ BTM_SetSecurityLevel (TRUE, "BTA_FTC", BTM_SEC_SERVICE_OBEX_FTP,
+ p_cb->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, p_data->sdp_ok.scn);
+ srm = 0;
+ nonce = 0;
+ }
+ else
+ {
+ BTM_SetSecurityLevel (TRUE, "BTA_FTC", BTM_SEC_SERVICE_OBEX_FTP,
+ p_cb->sec_mask, p_data->sdp_ok.psm, 0, 0);
+ }
+
+ if (status == OBX_SUCCESS)
+ {
+ OBX_CreateSession (p_cb->bd_addr, mtu, srm, nonce,
+ p_cb->obx_handle, p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* OBX will free the memory */
+ return;
+ }
+ /* else stay in this function to report failure */
+ return;
+ }
+ else
+ {
+ p_cb->status = BTA_FTC_OBX_ERR;
+ p_data->obx_evt.rsp_code = OBX_RSP_FAILED;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CLOSE_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_free_db
+**
+** Description Free buffer used for service discovery database.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_free_db(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ utl_freebuf((void**)&p_cb->p_db);
+ p_cb->sdp_pending = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_ignore_obx
+**
+** Description Free OBX packet for ignored OBX events.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_ignore_obx(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_find_service
+**
+** Description Perform service discovery to find OPP and/or FTP services on
+** peer device. If the service ID is both FTP and OPP then FTP
+** is tried first.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_find_service(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tSDP_UUID uuid_list;
+ UINT16 attr_list[5];
+ UINT16 num_attrs = 4;
+ tBTA_SERVICE_MASK ftc_services = (BTA_FTP_SERVICE_MASK | BTA_OPP_SERVICE_MASK
+ | BTA_BIP_SERVICE_MASK | BTA_PBAP_SERVICE_MASK);
+
+ APPL_TRACE_DEBUG1("bta_ftc_find_service event:0x%x", BTA_FTC_API_OPEN_EVT);
+
+ /* Make sure at least one service was specified */
+ if (p_cb->services & ftc_services)
+ {
+ if ((p_cb->p_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_FTC_DISC_SIZE)) != NULL)
+ {
+ p_cb->status = BTA_FTC_OK;
+
+ 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_OBX_OVR_L2CAP_PSM;
+
+ uuid_list.len = LEN_UUID_16;
+
+ /* Try FTP if its service is desired */
+ if (p_cb->services & BTA_FTP_SERVICE_MASK)
+ {
+ p_cb->services &= ~BTA_FTP_SERVICE_MASK;
+ p_cb->sdp_service = UUID_SERVCLASS_OBEX_FILE_TRANSFER;
+ uuid_list.uu.uuid16 = UUID_SERVCLASS_OBEX_FILE_TRANSFER;
+ }
+ else if (p_cb->services & BTA_PBAP_SERVICE_MASK)
+ {
+ p_cb->services &= ~BTA_PBAP_SERVICE_MASK;
+ p_cb->sdp_service = UUID_SERVCLASS_PBAP_PSE;
+ uuid_list.uu.uuid16 = UUID_SERVCLASS_PBAP_PSE;
+ }
+ else if (p_cb->services & BTA_OPP_SERVICE_MASK)
+ {
+ p_cb->services &= ~BTA_OPP_SERVICE_MASK;
+ p_cb->sdp_service = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
+ uuid_list.uu.uuid16 = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
+ }
+ else if (p_bta_ft_cfg->p_bi_action)
+ {
+ /* Try the basic imaging service */
+ p_cb->services &= ~BTA_BIP_SERVICE_MASK;
+ p_cb->sdp_service = UUID_SERVCLASS_IMAGING_RESPONDER;
+ uuid_list.uu.uuid16 = UUID_SERVCLASS_IMAGING_RESPONDER;
+ attr_list[num_attrs++] = ATTR_ID_SUPPORTED_FEATURES;
+ }
+
+ SDP_InitDiscoveryDb(p_cb->p_db, BTA_FTC_DISC_SIZE, 1, &uuid_list, num_attrs, attr_list);
+ if (!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db, bta_ftc_sdp_cback))
+ {
+ p_cb->status = BTA_FTC_SDP_ERR;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_SDP_FAIL_EVT, p_data);
+
+ }
+
+ p_cb->sdp_pending = TRUE;
+ }
+ }
+ else /* No services available */
+ {
+ p_cb->status = BTA_FTC_SERVICE_UNAVL;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_SDP_FAIL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_close_complete
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_close_complete(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC param;
+
+ param.status = p_cb->status;
+ p_cb->cout_active = FALSE;
+ bta_ftc_initialize(p_cb, p_data);
+
+ if (p_bta_ft_cfg->p_bi_action && p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_FREEXML_IDX])
+ (p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_FREEXML_IDX])(p_cb, p_data);
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_FTC ,p_cb->app_id, p_cb->bd_addr);
+ bta_fs_co_session_info(p_cb->bd_addr, p_cb->p_sess_info, 0, BTA_FS_CO_SESS_ST_NONE, NULL, NULL, p_cb->app_id);
+
+ p_cb->p_cback(BTA_FTC_CLOSE_EVT, &param);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_set_disable
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_set_disable(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ p_cb->disabling = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_bic_put
+**
+** Description Initiate a connection with a peer device's service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_bic_put(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ if (p_bta_ft_cfg->p_bi_action &&
+ p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_PUT_IDX])
+ {
+ p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_PUT_IDX](p_cb, p_data);
+ }
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_bic_abort
+**
+** Description Initiate a connection with a peer device's service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_bic_abort(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ if (p_bta_ft_cfg->p_bi_action &&
+ p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_ABORT_IDX])
+ {
+ p_bta_ft_cfg->p_bi_action[BTA_FTC_BI_ABORT_IDX](p_cb, p_data);
+ }
+ return;
+}
+
+/*****************************************************************************
+** Callback Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ftc_obx_cback
+**
+** Description OBX callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event, UINT8 rsp_code,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_FTC_OBX_EVT *p_obx_msg;
+ UINT16 event = 0;
+ UINT16 size = sizeof(tBTA_FTC_OBX_EVT);
+
+#if BTA_FTC_DEBUG == TRUE
+ APPL_TRACE_DEBUG2("OBX Event Callback: obx_event [%s] 0x%x", ftc_obx_evt_code(obx_event), p_pkt);
+#endif
+
+ switch (obx_event)
+ {
+ case OBX_SESSION_INFO_EVT:
+ size += OBX_SESSION_INFO_SIZE;
+ /* Falls through */
+
+ case OBX_SESSION_RSP_EVT:
+ case OBX_CONNECT_RSP_EVT:
+ if (rsp_code == OBX_RSP_OK)
+ {
+ event = BTA_FTC_OBX_CONN_RSP_EVT;
+ }
+ else /* Obex will disconnect underneath BTA */
+ {
+ APPL_TRACE_WARNING1("FTC_CBACK: Bad connect response 0x%02x", rsp_code);
+ if (p_pkt)
+ GKI_freebuf(p_pkt);
+ return;
+ }
+ break;
+
+ case OBX_ACTION_RSP_EVT:
+ event = BTA_FTC_OBX_ACTION_RSP_EVT;
+ break;
+
+ case OBX_PUT_RSP_EVT:
+ event = BTA_FTC_OBX_PUT_RSP_EVT;
+ break;
+ case OBX_GET_RSP_EVT:
+ event = BTA_FTC_OBX_GET_RSP_EVT;
+ break;
+ case OBX_SETPATH_RSP_EVT:
+ event = BTA_FTC_OBX_SETPATH_RSP_EVT;
+ break;
+ case OBX_ABORT_RSP_EVT:
+ event = BTA_FTC_OBX_ABORT_RSP_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_FTC_OBX_CLOSE_EVT;
+ break;
+ case OBX_TIMEOUT_EVT:
+ event = BTA_FTC_OBX_TOUT_EVT;
+ break;
+ case OBX_PASSWORD_EVT:
+ event = BTA_FTC_OBX_PASSWORD_EVT;
+ break;
+
+ default:
+ /* case OBX_DISCONNECT_RSP_EVT: Handled when OBX_CLOSE_IND_EVT arrives */
+ if (p_pkt)
+ GKI_freebuf(p_pkt);
+ return;
+
+ }
+
+ /* send event to BTA, if any */
+ if ((p_obx_msg = (tBTA_FTC_OBX_EVT *) GKI_getbuf(size)) != NULL)
+ {
+ APPL_TRACE_DEBUG2("obx_event [%d] event:0x%x", obx_event, event);
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->rsp_code = rsp_code;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+
+ if (obx_event == OBX_SESSION_INFO_EVT)
+ {
+ p_obx_msg->param.sess.p_sess_info = (UINT8 *)(p_obx_msg + 1);
+ memcpy (p_obx_msg->param.sess.p_sess_info, param.sess.p_sess_info, OBX_SESSION_INFO_SIZE);
+ }
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+
+
+/******************************************************************************
+**
+** Function bta_ftc_sdp_cback
+**
+** Description This is the SDP callback function used by FTC.
+** 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 Nothing.
+**
+******************************************************************************/
+static void bta_ftc_sdp_cback(UINT16 status)
+{
+ tBTA_FTC_CB *p_cb = &bta_ftc_cb;
+ tBTA_FTC_SDP_OK_EVT *p_buf;
+ tSDP_DISC_REC *p_rec = NULL;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT8 scn = 0;
+ UINT16 psm = 0;
+ UINT16 version = GOEP_LEGACY_VERSION;
+ BOOLEAN found = FALSE;
+ tSDP_DISC_ATTR *p_attr;
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ tBIP_FEATURE_FLAGS features = 0;
+#endif
+
+ APPL_TRACE_DEBUG1("bta_ftc_sdp_cback status:%d", status);
+
+ if ( (status == SDP_SUCCESS) || (status == SDP_DB_FULL) )
+ {
+ status = SDP_SUCCESS;
+ /* loop through all records we found */
+ do
+ {
+ /* get next record; if none found, we're done */
+ if ((p_rec = SDP_FindServiceInDb(p_cb->p_db, p_cb->sdp_service,
+ p_rec)) == NULL)
+ break;
+
+ /* this is an optional attribute */
+ SDP_FindProfileVersionInRec (p_rec, p_cb->sdp_service, &version);
+
+ /* get psm from proto desc list alternative; if not found, go to next record */
+ if ((p_attr = SDP_FindAttributeInRec(p_rec,
+ ATTR_ID_OBX_OVR_L2CAP_PSM)) != NULL)
+ {
+ psm = p_attr->attr_value.v.u16;
+ APPL_TRACE_DEBUG1("attr_len_type: x%x", p_attr->attr_len_type);
+ if ((SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2) && L2C_IS_VALID_PSM(psm))
+ {
+ found = TRUE;
+ if (version == GOEP_LEGACY_VERSION)
+ {
+ APPL_TRACE_ERROR0("Lacking mandatory attribute/version");
+ version = BTA_FT_ENHANCED_VERSION;
+ }
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ /* get scn from proto desc list; if not found, go to next record */
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ if ( p_bta_ft_cfg->p_bi_action && p_cb->sdp_service == UUID_SERVCLASS_IMAGING_RESPONDER)
+ {
+ /* Check if the Push feature is supported */
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES)) != NULL)
+ {
+ features = p_attr->attr_value.v.u16;
+ APPL_TRACE_DEBUG1("supported BIP features: x%x", features);
+ if (features & BIP_FT_IMG_PUSH_FLAGS)
+ {
+ found = TRUE;
+ }
+ }
+#endif
+ }
+ else
+ {
+ found = TRUE;
+ }
+ scn = (UINT8) pe.params[0];
+
+ /* we've got everything, we're done */
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ } while (TRUE);
+ }
+
+ APPL_TRACE_DEBUG4("found: %d scn:%d, psm:0x%x version:0x%x",found , scn, psm, version);
+
+ /* send result in event back to BTA */
+ if ((p_buf = (tBTA_FTC_SDP_OK_EVT *) GKI_getbuf(sizeof(tBTA_FTC_SDP_OK_EVT))) != NULL)
+ {
+ p_buf->hdr.event = BTA_FTC_SDP_FAIL_EVT;
+ p_cb->status = BTA_FTC_SERVICE_UNAVL;
+
+ if (status == SDP_SUCCESS)
+ {
+ if (found == TRUE)
+ {
+ p_buf->hdr.event = BTA_FTC_SDP_OK_EVT;
+ p_buf->scn = scn;
+ p_buf->psm = psm;
+ p_buf->version = version;
+ }
+ /* See if OPP service needs to be searched for */
+ else if (p_cb->services & (BTA_OPP_SERVICE_MASK|BTA_BIP_SERVICE_MASK))
+ {
+ p_buf->hdr.event = BTA_FTC_SDP_NEXT_EVT;
+ }
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*****************************************************************************
+** Local FTP Event Processing Functions
+*****************************************************************************/
+static void ftc_reset_cb (tBTA_FTC_CB *p_cb)
+{
+ /* Clean up control block */
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+ utl_freebuf((void**)(BT_HDR **)&p_cb->p_name);
+ p_cb->obx_oper = FTC_OP_NONE;
+ p_cb->aborting = 0;
+ p_cb->int_abort = FALSE;
+ p_cb->req_pending = FALSE;
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_FTC_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function ftc_obx_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ftc_obx_evt_code(tOBX_EVENT evt_code)
+{
+ switch (evt_code)
+ {
+ case OBX_CONNECT_RSP_EVT:
+ return "OBX_CONNECT_RSP_EVT";
+ case OBX_DISCONNECT_RSP_EVT:
+ return "OBX_DISCONNECT_RSP_EVT";
+ case OBX_PUT_RSP_EVT:
+ return "OBX_PUT_RSP_EVT";
+ case OBX_GET_RSP_EVT:
+ return "OBX_GET_RSP_EVT";
+ case OBX_SETPATH_RSP_EVT:
+ return "OBX_SETPATH_RSP_EVT";
+ case OBX_ABORT_RSP_EVT:
+ return "OBX_ABORT_RSP_EVT";
+ case OBX_CLOSE_IND_EVT:
+ return "OBX_CLOSE_IND_EVT";
+ case OBX_TIMEOUT_EVT:
+ return "OBX_TIMEOUT_EVT";
+ case OBX_PASSWORD_EVT:
+ return "OBX_PASSWORD_EVT";
+ case OBX_SESSION_RSP_EVT:
+ return "OBX_SESSION_RSP_EVT";
+ case OBX_ACTION_RSP_EVT:
+ return "OBX_ACTION_RSP_EVT";
+ case OBX_SESSION_INFO_EVT:
+ return "OBX_SESSION_INFO_EVT";
+ default:
+ return "unknown OBX event code";
+ }
+}
+#endif /* Debug Functions */
+#endif /* BTA_FT_INCLUDED */
diff --git a/bta/ft/bta_ftc_api.c b/bta/ft/bta_ftc_api.c
new file mode 100644
index 0000000..31722cf
--- /dev/null
+++ b/bta/ft/bta_ftc_api.c
@@ -0,0 +1,796 @@
+/*****************************************************************************
+**
+** Name: bta_ftc_api.c
+**
+** Description: This is the implementation of the API for the file
+** transfer server subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#include "bt_target.h"
+
+#if defined(BTA_FT_INCLUDED) && (BTA_FT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_fs_api.h"
+#include "bta_ftc_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+static const tBTA_SYS_REG bta_ftc_reg =
+{
+ bta_ftc_hdl_event,
+ BTA_FtcDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_FtcEnable
+**
+** Description Enable the file transfer client. This function must be
+** called before any other functions in the FTC API are called.
+** When the enable operation is complete the callback function
+** will be called with an BTA_FTC_ENABLE_EVT event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcEnable(tBTA_FTC_CBACK *p_cback, UINT8 app_id)
+{
+ tBTA_FTC_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_FTC, &bta_ftc_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_FTC_API_ENABLE *)GKI_getbuf(sizeof(tBTA_FTC_API_ENABLE))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_FTC_API_ENABLE));
+
+ p_buf->hdr.event = BTA_FTC_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->app_id = app_id;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcDisable
+**
+** Description Disable the file transfer client. If the client is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_FTC);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_FTC_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcOpen
+**
+** Description Open a connection to an FTP, PBAP, OPP or BIP server.
+** If parameter services is set to use both all services,
+** the client will attempt to connect to the device using
+** FTP first and then PBAP, OPP, BIP.
+** When the connection is open the callback function
+** will be called with a BTA_FTC_OPEN_EVT. If the connection
+** fails or otherwise is closed the callback function will be
+** called with a BTA_FTC_CLOSE_EVT.
+**
+** If the connection is opened with FTP profile and
+** bta_ft_cfg.auto_file_list is TRUE , the callback
+** function will be called with one or more BTA_FTC_LIST_EVT
+** containing directory list information formatted in XML as
+** described in the IrOBEX Spec, Version 1.2, section 9.1.2.3.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcOpen(BD_ADDR bd_addr, tBTA_SEC sec_mask, tBTA_SERVICE_MASK services,
+ BOOLEAN srm, UINT32 nonce)
+{
+ tBTA_FTC_API_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_FTC_API_OPEN *)GKI_getbuf(sizeof(tBTA_FTC_API_OPEN))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_FTC_API_OPEN));
+
+ p_buf->hdr.event = BTA_FTC_API_OPEN_EVT;
+ p_buf->services = services;
+ p_buf->sec_mask = sec_mask;
+ p_buf->srm = srm;
+ p_buf->nonce = nonce;
+ memcpy(p_buf->bd_addr, bd_addr, BD_ADDR_LEN);
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcSuspend
+**
+** Description Suspend the current connection to the server.
+** This is allowed only for the sessions created by
+** BTA_FtcConnect with nonce!=0
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcSuspend(void)
+{
+ tBTA_FTC_API_CLOSE *p_buf;
+
+ APPL_TRACE_DEBUG0("BTA_FtcSuspend");
+ if ((p_buf = (tBTA_FTC_API_CLOSE *)GKI_getbuf(sizeof(tBTA_FTC_API_CLOSE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_FTC_API_CLOSE_EVT;
+ p_buf->suspend = TRUE;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcClose
+**
+** Description Close the current connection to the server.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcClose(void)
+{
+ tBTA_FTC_API_CLOSE *p_buf;
+
+ if ((p_buf = (tBTA_FTC_API_CLOSE *)GKI_getbuf(sizeof(tBTA_FTC_API_CLOSE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_FTC_API_CLOSE_EVT;
+ p_buf->suspend = FALSE;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcCopyFile
+**
+** Description Invoke a Copy action on the server.
+** Create a copy of p_src and name it as p_dest
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcCopyFile(const char *p_src, const char *p_dest)
+{
+ tBTA_FTC_API_ACTION *p_buf;
+ UINT16 src_len = (p_src) ? strlen(p_src) : 0;
+ UINT16 dest_len = (p_dest) ? strlen(p_dest) : 0;
+ UINT16 total_len = sizeof(tBTA_FTC_API_ACTION) + src_len + dest_len + 2;
+
+ APPL_TRACE_DEBUG2("BTA_FtcCopyFile src:%s, dest:%s", p_src, p_dest);
+
+ if ((p_buf = (tBTA_FTC_API_ACTION *)GKI_getbuf( total_len)) != NULL)
+ {
+ p_buf->hdr.event = BTA_FTC_API_ACTION_EVT;
+ p_buf->action = BTA_FT_ACT_COPY;
+ p_buf->p_src = (char *)(p_buf + 1);
+ p_buf->p_dest = (char *)(p_buf->p_src + src_len + 1);
+ /* copy the src name */
+ if (p_src)
+ {
+ BCM_STRNCPY_S(p_buf->p_src, src_len+1, p_src, src_len);
+ p_buf->p_src[src_len] = '\0';
+ }
+ else
+ p_buf->p_src[0] = '\0';
+
+ /* copy the dest name */
+ if (p_dest)
+ {
+ BCM_STRNCPY_S(p_buf->p_dest, dest_len+1, p_dest, dest_len);
+ p_buf->p_dest[dest_len] = '\0';
+ }
+ else
+ p_buf->p_dest[0] = '\0';
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcMoveFile
+**
+** Description Invoke a Move action on the server.
+** Move/rename p_src to p_dest
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcMoveFile(const char *p_src, const char *p_dest)
+{
+ tBTA_FTC_API_ACTION *p_buf;
+ UINT16 src_len = (p_src) ? strlen(p_src) : 0;
+ UINT16 dest_len = (p_dest) ? strlen(p_dest) : 0;
+ UINT16 total_len = sizeof(tBTA_FTC_API_ACTION) + src_len + dest_len + 2;
+
+ APPL_TRACE_DEBUG2("BTA_FtcMoveFile src:%s, dest:%s", p_src, p_dest);
+
+ if ((p_buf = (tBTA_FTC_API_ACTION *)GKI_getbuf(total_len)) != NULL)
+ {
+ p_buf->hdr.event = BTA_FTC_API_ACTION_EVT;
+ p_buf->action = BTA_FT_ACT_MOVE;
+ p_buf->p_src = (char *)(p_buf + 1);
+ p_buf->p_dest = (char *)(p_buf->p_src + src_len + 1);
+
+ /* copy the src name */
+ if (p_src)
+ {
+ BCM_STRNCPY_S(p_buf->p_src, src_len+1, p_src, src_len);
+ p_buf->p_src[src_len] = '\0';
+ }
+ else
+ p_buf->p_src[0] = '\0';
+
+ /* copy the dest name */
+ if (p_dest)
+ {
+ BCM_STRNCPY_S(p_buf->p_dest, dest_len+1, p_dest, dest_len);
+ p_buf->p_dest[dest_len] = '\0';
+ }
+ else
+ p_buf->p_dest[0] = '\0';
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcSetPermission
+**
+** Description Invoke a SetPermission action on the server.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcSetPermission(const char *p_src, UINT8 user, UINT8 group, UINT8 other)
+{
+ tBTA_FTC_API_ACTION *p_buf;
+ UINT16 src_len = (p_src) ? strlen(p_src) : 0;
+ UINT16 total_len = sizeof(tBTA_FTC_API_ACTION) + src_len + 1;
+
+ APPL_TRACE_DEBUG4("BTA_FtcSetPermission src:%s, user:0x%x, group:0x%x, other:0x%x",
+ p_src, user, group, other);
+
+ if ((p_buf = (tBTA_FTC_API_ACTION *)GKI_getbuf(total_len)) != NULL)
+ {
+ p_buf->hdr.event = BTA_FTC_API_ACTION_EVT;
+ p_buf->action = BTA_FT_ACT_PERMISSION;
+ p_buf->p_src = (char *)(p_buf + 1);
+
+ /* copy the src name */
+ if (p_src)
+ {
+ BCM_STRNCPY_S(p_buf->p_src, src_len+1, p_src, src_len);
+ p_buf->p_src[src_len] = '\0';
+ }
+ else
+ p_buf->p_src[0] = '\0';
+
+ p_buf->permission[0] = user;
+ p_buf->permission[1] = group;
+ p_buf->permission[2] = other;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcPutFile
+**
+** Description Send a file to the connected server.
+** This function can only be used when the client is connected
+** in FTP, OPP and BIP mode.
+**
+** Note: File name is specified with a fully qualified path.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcPutFile(const char *p_name, tBTA_FTC_PARAM *p_param)
+{
+ tBTA_FTC_DATA *p_msg;
+ INT32 name_len = (INT32)((p_bta_fs_cfg->max_path_len + 1 + 3)/4)*4;
+
+ if ((p_msg = (tBTA_FTC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_DATA) +
+ sizeof(tBTA_FTC_PARAM) + name_len))) != NULL)
+ {
+ p_msg->api_put.p_name = (char *)(p_msg + 1);
+
+ if (p_name != NULL)
+ BCM_STRNCPY_S(p_msg->api_put.p_name, name_len, p_name, p_bta_fs_cfg->max_path_len);
+ else
+ p_msg->api_put.p_name[0] = 0;
+
+ if(p_param)
+ {
+ p_msg->api_put.p_param = (tBTA_FTC_PARAM *)(p_msg->api_put.p_name + name_len);
+ memcpy(p_msg->api_put.p_param, p_param, sizeof(tBTA_FTC_PARAM));
+ }
+ else
+ p_msg->api_put.p_param = NULL;
+
+ p_msg->api_put.hdr.event = BTA_FTC_API_PUTFILE_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcGetPhoneBook
+**
+** Description Retrieve a PhoneBook from the peer device and copy it to the
+** local file system.
+**
+** This function can only be used when the client is connected
+** in PBAP mode.
+**
+** Note: local file name is specified with a fully qualified path.
+** Remote file name is absolute path in UTF-8 format.
+** (telecom/pb.vcf or SIM1/telecom/pb.vcf).
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcGetPhoneBook(char *p_local_name, char *p_remote_name,
+ tBTA_FTC_FILTER_MASK filter, tBTA_FTC_FORMAT format,
+ UINT16 max_list_count, UINT16 list_start_offset)
+{
+ tBTA_FTC_DATA *p_msg;
+ tBTA_FTC_API_GET *p_get;
+ tBTA_FTC_GET_PARAM *p_getp;
+ UINT16 remote_name_length = (p_remote_name) ? strlen(p_remote_name) : 0;
+
+ if ((p_msg = (tBTA_FTC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_DATA) +
+ (p_bta_fs_cfg->max_path_len + 1) + remote_name_length + 1))) != NULL)
+ {
+ p_get = &p_msg->api_get;
+ p_get->p_param = (tBTA_FTC_GET_PARAM *)(p_msg + 1);
+ p_getp = p_get->p_param;
+ p_get->p_rem_name = (char *)(p_getp + 1);
+ p_get->p_name = (char *)(p_get->p_rem_name + remote_name_length + 1);
+ p_get->obj_type = BTA_FTC_GET_PB;
+
+ /* copy the local name */
+ if (p_local_name)
+ BCM_STRNCPY_S(p_get->p_name, p_bta_fs_cfg->max_path_len + 1, p_local_name, p_bta_fs_cfg->max_path_len);
+ else
+ p_get->p_name[0] = '\0';
+
+ /* copy remote name */
+ if( p_remote_name)
+ BCM_STRNCPY_S(p_get->p_rem_name, remote_name_length + 1, p_remote_name, remote_name_length);
+ p_get->p_rem_name[remote_name_length] = '\0';
+
+ p_getp->filter = filter;
+ p_getp->format = format;
+ p_getp->list_start_offset = list_start_offset;
+ p_getp->max_list_count = max_list_count;
+
+ p_get->hdr.event = BTA_FTC_API_GETFILE_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcGetCard
+**
+** Description Retrieve a vCard from the peer device and copy it to the
+** local file system.
+**
+** This function can only be used when the client is connected
+** in PBAP mode.
+**
+** Note: local file name is specified with a fully qualified path.
+** Remote file name is relative path in UTF-8 format.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcGetCard(char *p_local_name, char *p_remote_name,
+ tBTA_FTC_FILTER_MASK filter, tBTA_FTC_FORMAT format)
+{
+ tBTA_FTC_DATA *p_msg;
+ tBTA_FTC_API_GET *p_get;
+ tBTA_FTC_GET_PARAM *p_getp;
+ UINT16 remote_name_length = (p_remote_name) ? strlen(p_remote_name) : 0;
+
+ if ((p_msg = (tBTA_FTC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_DATA) +
+ (p_bta_fs_cfg->max_path_len + 1) + remote_name_length + 1))) != NULL)
+ {
+ p_get = &p_msg->api_get;
+ p_get->p_param = (tBTA_FTC_GET_PARAM *)(p_msg + 1);
+ p_getp = p_get->p_param;
+ p_get->p_rem_name = (char *)(p_getp + 1);
+ p_get->p_name = (char *)(p_get->p_rem_name + remote_name_length + 1);
+ p_get->obj_type = BTA_FTC_GET_CARD;
+
+ /* copy the local name */
+ if (p_local_name)
+ {
+ BCM_STRNCPY_S(p_get->p_name, p_bta_fs_cfg->max_path_len + 1, p_local_name, p_bta_fs_cfg->max_path_len);
+ p_get->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ p_get->p_name[0] = '\0';
+
+ /* copy remote name */
+ if( p_remote_name)
+ BCM_STRNCPY_S(p_get->p_rem_name, remote_name_length+1, p_remote_name, remote_name_length);
+ p_get->p_rem_name[remote_name_length] = '\0';
+
+ p_getp->filter = filter;
+ p_getp->format = format;
+
+ p_get->hdr.event = BTA_FTC_API_GETFILE_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcGetFile
+**
+** Description Retrieve a file from the peer device and copy it to the
+** local file system.
+**
+** This function can only be used when the client is connected
+** in FTP mode.
+**
+** Note: local file name is specified with a fully qualified path.
+** Remote file name is specified in UTF-8 format.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcGetFile(char *p_local_name, char *p_remote_name)
+{
+ tBTA_FTC_DATA *p_msg;
+ tBTA_FTC_API_GET *p_get;
+ UINT16 remote_name_length = (p_remote_name) ? strlen(p_remote_name) : 0;
+
+ if ((p_msg = (tBTA_FTC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_DATA) +
+ (p_bta_fs_cfg->max_path_len + 1) + remote_name_length + 1))) != NULL)
+ {
+ p_get = &p_msg->api_get;
+ p_get->obj_type = BTA_FTC_GET_FILE;
+ p_get->p_param = NULL;
+ p_get->p_rem_name = (char *)(p_msg + 1);
+ p_get->p_name = (char *)(p_msg->api_get.p_rem_name + remote_name_length + 1);
+
+ /* copy the local name */
+ if (p_local_name)
+ {
+ BCM_STRNCPY_S(p_get->p_name, p_bta_fs_cfg->max_path_len + 1, p_local_name, p_bta_fs_cfg->max_path_len);
+ p_get->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ p_get->p_name[0] = '\0';
+
+ /* copy remote name */
+ if( p_remote_name)
+ BCM_STRNCPY_S(p_get->p_rem_name, remote_name_length+1, p_remote_name, remote_name_length);
+ p_get->p_rem_name[remote_name_length] = '\0';
+
+
+ p_get->hdr.event = BTA_FTC_API_GETFILE_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcChDir
+**
+** Description Change directory on the peer device.
+**
+** This function can only be used when the client is connected
+** in FTP and PBAP mode.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcChDir(char *p_dir, tBTA_FTC_FLAG flag)
+{
+ tBTA_FTC_DATA *p_msg;
+ tBTA_FTC_API_CHDIR *p_chdir;
+ UINT16 dir_len;
+
+ /* If directory is specified set the length */
+ dir_len = (p_dir && *p_dir != '\0') ? (UINT16)(strlen(p_dir) + 1): 0;
+
+ if ((p_msg = (tBTA_FTC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_DATA) +
+ dir_len))) != NULL)
+ {
+ p_chdir = &p_msg->api_chdir;
+ p_chdir->flag = flag;
+ if (dir_len)
+ {
+ p_chdir->p_dir = (char *)(p_msg + 1);
+ BCM_STRNCPY_S(p_chdir->p_dir, dir_len, p_dir, dir_len);
+ }
+ else /* Setting to root directory OR backing up a directory */
+ p_chdir->p_dir = NULL;
+
+ p_chdir->hdr.event = BTA_FTC_API_CHDIR_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcAuthRsp
+**
+** Description Sends a response to an OBEX authentication challenge to the
+** connected OBEX server. Called in response to an BTA_FTC_AUTH_EVT
+** event.
+**
+** Note: If the "userid_required" is TRUE in the BTA_FTC_AUTH_EVT event,
+** then p_userid is required, otherwise it is optional.
+**
+** p_password must be less than BTA_FTC_MAX_AUTH_KEY_SIZE (16 bytes)
+** p_userid must be less than OBX_MAX_REALM_LEN (defined in target.h)
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcAuthRsp (char *p_password, char *p_userid)
+{
+ tBTA_FTC_API_AUTHRSP *p_auth_rsp;
+
+ if ((p_auth_rsp = (tBTA_FTC_API_AUTHRSP *)GKI_getbuf(sizeof(tBTA_FTC_API_AUTHRSP))) != NULL)
+ {
+ memset(p_auth_rsp, 0, sizeof(tBTA_FTC_API_AUTHRSP));
+
+ p_auth_rsp->hdr.event = BTA_FTC_API_AUTHRSP_EVT;
+
+ if (p_password)
+ {
+ p_auth_rsp->key_len = strlen(p_password);
+ if (p_auth_rsp->key_len > BTA_FTC_MAX_AUTH_KEY_SIZE)
+ p_auth_rsp->key_len = BTA_FTC_MAX_AUTH_KEY_SIZE;
+ memcpy(p_auth_rsp->key, p_password, p_auth_rsp->key_len);
+ }
+
+ if (p_userid)
+ {
+ p_auth_rsp->userid_len = strlen(p_userid);
+ if (p_auth_rsp->userid_len > OBX_MAX_REALM_LEN)
+ p_auth_rsp->userid_len = OBX_MAX_REALM_LEN;
+ memcpy(p_auth_rsp->userid, p_userid, p_auth_rsp->userid_len);
+ }
+
+ bta_sys_sendmsg(p_auth_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcListCards
+**
+** Description Retrieve a directory listing from the peer device.
+** When the operation is complete the callback function will
+** be called with one or more BTA_FTC_LIST_EVT events
+** containing directory list information formatted as described
+** in the PBAP Spec, Version 0.9, section 3.1.6.
+** This function can only be used when the client is connected
+** to a peer device.
+**
+** This function can only be used when the client is connected
+** in PBAP mode.
+**
+** Parameters p_dir - Name of directory to retrieve listing of.
+**
+** Returns void
+**
+*******************************************************************************/
+
+void BTA_FtcListCards(char *p_dir, tBTA_FTC_ORDER order, char *p_value,
+ tBTA_FTC_ATTR attribute, UINT16 max_list_count,
+ UINT16 list_start_offset)
+{
+ tBTA_FTC_DATA *p_msg;
+ tBTA_FTC_API_LIST *p_list;
+ tBTA_FTC_LST_PARAM *p_param;
+ UINT16 dir_len = (p_dir == NULL) ? 0 : strlen(p_dir) ;
+ UINT16 value_len = (p_value == NULL) ? 0 : strlen(p_value) ;
+
+ if ((p_msg = (tBTA_FTC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_DATA) +
+ sizeof(tBTA_FTC_LST_PARAM) +
+ dir_len + value_len + 2))) != NULL)
+ {
+ p_list = &p_msg->api_list;
+ p_list->p_param = (tBTA_FTC_LST_PARAM *)(p_msg + 1);
+ p_param = p_list->p_param;
+ p_list->p_dir = (char *)(p_param + 1);
+ p_param->order = order;
+ p_param->attribute = attribute;
+ p_param->max_list_count = max_list_count;
+ p_param->list_start_offset = list_start_offset;
+
+ if (dir_len)
+ BCM_STRNCPY_S(p_list->p_dir, dir_len+1, p_dir, dir_len);
+ p_list->p_dir[dir_len] = 0;
+
+ if (value_len)
+ {
+ p_param->p_value = (char *)(p_list->p_dir + dir_len + 1);
+ BCM_STRNCPY_S(p_param->p_value, value_len+1, p_value, value_len);
+ p_param->p_value[value_len] = 0;
+ }
+ else
+ p_param->p_value = NULL;
+
+ p_list->hdr.event = BTA_FTC_API_LISTDIR_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcListDir
+**
+** Description Retrieve a directory listing from the peer device.
+** When the operation is complete the callback function will
+** be called with one or more BTA_FTC_LIST_EVT events
+** containing directory list information formatted as described
+** in the IrOBEX Spec, Version 1.2, section 9.1.2.3.
+**
+** This function can only be used when the client is connected
+** in FTP mode.
+**
+** Parameters p_dir - Name of directory to retrieve listing of. If NULL,
+** the current working directory is retrieved.
+**
+** Returns void
+**
+*******************************************************************************/
+
+void BTA_FtcListDir(char *p_dir)
+{
+ tBTA_FTC_DATA *p_msg;
+ tBTA_FTC_API_LIST *p_list;
+ UINT16 dir_len = (p_dir == NULL) ? 0 : strlen(p_dir) ;
+
+ if ((p_msg = (tBTA_FTC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_DATA) +
+ dir_len + 1))) != NULL)
+ {
+ p_list = &p_msg->api_list;
+ p_list->p_dir = (char *)(p_msg + 1);
+ p_list->p_param = NULL;
+
+ if (dir_len)
+ BCM_STRNCPY_S(p_list->p_dir, dir_len+1, p_dir, dir_len);
+
+ p_list->p_dir[dir_len] = 0;
+
+ p_list->hdr.event = BTA_FTC_API_LISTDIR_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcMkDir
+**
+** Description Create a directory on the peer device. When the operation is
+** complete the status is returned with the BTA_FTC_MKDIR_EVT
+** event.
+**
+** This function can only be used when the client is connected
+** in FTP mode.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcMkDir(char *p_dir)
+{
+ tBTA_FTC_API_MKDIR *p_mkdir;
+ UINT16 len = (p_dir == NULL) ? 0: strlen(p_dir);
+
+ if ((p_mkdir = (tBTA_FTC_API_MKDIR *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_API_MKDIR) +
+ len + 1))) != NULL)
+ {
+ p_mkdir->p_dir = (char *)(p_mkdir + 1);
+
+ if (len > 0)
+ BCM_STRNCPY_S(p_mkdir->p_dir, len+1, p_dir, len);
+
+ p_mkdir->p_dir[len] = 0;
+
+ p_mkdir->hdr.event = BTA_FTC_API_MKDIR_EVT;
+ bta_sys_sendmsg(p_mkdir);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtcRemove
+**
+** Description Remove a file or directory on the peer device. When the
+** operation is complete the status is returned with the
+** BTA_FTC_REMOVE_EVT event.
+**
+** This function can only be used when the client is connected
+** in FTP mode.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcRemove(char *p_name)
+
+{
+ tBTA_FTC_DATA *p_msg;
+ tBTA_FTC_API_REMOVE *p_remove;
+ UINT16 len = (p_name == NULL) ? 0 :strlen(p_name);
+
+ if ((p_msg = (tBTA_FTC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_FTC_DATA) +
+ len + 1))) != NULL)
+ {
+ p_remove = &p_msg->api_remove;
+ p_remove->p_name = (char *)(p_msg +1);
+ if(len)
+ BCM_STRNCPY_S(p_remove->p_name, len+1, p_name, len);
+
+ p_remove->p_name[len] = 0;
+
+ p_remove->hdr.event = BTA_FTC_API_REMOVE_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function BTA_FtcAbort
+**
+** Description Aborts any active Put or Get file operation.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtcAbort(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_FTC_API_ABORT_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+#endif /* BTA_FT_INCLUDED */
diff --git a/bta/ft/bta_ftc_int.h b/bta/ft/bta_ftc_int.h
new file mode 100644
index 0000000..4279aa6
--- /dev/null
+++ b/bta/ft/bta_ftc_int.h
@@ -0,0 +1,504 @@
+/*****************************************************************************
+**
+** Name: bta_ftc_int.h
+**
+** Description: This is the private file for the file transfer
+** client (FTC).
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_FTC_INT_H
+#define BTA_FTC_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_ft_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+#include "bta_bi_api.h"
+#endif
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+#define BTA_FTC_PB_ACCESS_TARGET_UUID "\x79\x61\x35\xF0\xF0\xC5\x11\xD8\x09\x66\x08\x00\x20\x0C\x9A\x66"
+#define BTA_FTC_FOLDER_BROWSING_TARGET_UUID "\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
+#define BTA_FTC_UUID_LENGTH 16
+#define BTA_FTC_MAX_AUTH_KEY_SIZE 16 /* Must not be greater than OBX_MAX_AUTH_KEY_SIZE */
+#define BTA_FTC_DEFAULT_VERSION 0x0100 /* for PBAP PCE */
+
+#define BTA_FTC_FOLDER_LISTING_TYPE "x-obex/folder-listing"
+
+#define BTA_FTC_PULL_PB_TYPE "x-bt/phonebook"
+#define BTA_FTC_PULL_VCARD_LISTING_TYPE "x-bt/vcard-listing"
+#define BTA_FTC_PULL_VCARD_ENTRY_TYPE "x-bt/vcard"
+
+/* FTC Active ftp obex operation (Valid in connected state) */
+#define FTC_OP_NONE 0
+#define FTC_OP_GET_FILE 1
+#define FTC_OP_PUT_FILE 2
+#define FTC_OP_DELETE 3 /* Folder or File */
+#define FTC_OP_GET_LIST 4
+#define FTC_OP_MKDIR 5
+#define FTC_OP_CHDIR 6
+/* note: the following 3 OPs need to be continuous and the order can not change */
+#define FTC_OP_COPY 7 /* Copy object */
+#define FTC_OP_MOVE 8 /* Move/rename object */
+#define FTC_OP_PERMISSION 9 /* Set object permission */
+#define FTC_OP_RESUME 0x80 /* to mark the operation to resume */
+
+enum
+{
+ BTA_FTC_GET_FILE, /* get file */
+ BTA_FTC_GET_CARD, /* PBAP PullvCardEntry */
+ BTA_FTC_GET_PB /* PBAP PullPhoneBook */
+};
+typedef UINT8 tBTA_FTC_TYPE;
+
+/* Response Timer Operations */
+#define FTC_TIMER_OP_STOP 0
+#define FTC_TIMER_OP_ABORT 1
+#define FTC_TIMER_OP_SUSPEND 2
+
+/* File abort mask states */
+/* Abort must receive cout and response before abort completed */
+#define FTC_ABORT_REQ_NOT_SENT 0x1
+#define FTC_ABORT_REQ_SENT 0x2
+#define FTC_ABORT_RSP_RCVD 0x4
+#define FTC_ABORT_COUT_DONE 0x8
+
+#define FTC_ABORT_COMPLETED (FTC_ABORT_REQ_SENT | FTC_ABORT_RSP_RCVD | FTC_ABORT_COUT_DONE)
+
+/* TODO remove: Reliable session suspend mask states */
+/* suspend must receive cout and response before suspend completed
+#define FTC_SUSPEND_REQ_NOT_SENT 0x10 */
+
+/* state machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_FTC_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_FTC),
+
+ BTA_FTC_API_OPEN_EVT, /* Open a connection request */
+ BTA_FTC_API_CLOSE_EVT, /* Close an open connection request */
+ BTA_FTC_API_PUTFILE_EVT, /* Put File request */
+ BTA_FTC_API_GETFILE_EVT, /* Get File request */
+ BTA_FTC_API_LISTDIR_EVT, /* List Directory request */
+ BTA_FTC_API_CHDIR_EVT, /* Change Directory request */
+ BTA_FTC_API_MKDIR_EVT, /* make Directory request */
+ BTA_FTC_API_REMOVE_EVT, /* Remove Directory request */
+ BTA_FTC_API_AUTHRSP_EVT, /* Response to password request */
+ BTA_FTC_API_ABORT_EVT, /* Abort request */
+ BTA_FTC_API_ACTION_EVT, /* Action request */
+ BTA_FTC_OBX_ACTION_RSP_EVT, /* Copy/Move File or Set Permission */
+ BTA_FTC_CI_SESSION_EVT, /* Call-in response to session requests */
+ BTA_FTC_SDP_OK_EVT, /* Service search was successful */
+ BTA_FTC_SDP_FAIL_EVT, /* Service search failed */
+ BTA_FTC_SDP_NEXT_EVT, /* Try another service search (OPP) */
+ BTA_FTC_CI_WRITE_EVT, /* Call-in response to Write request */
+ BTA_FTC_CI_READ_EVT, /* Call-in response to Read request */
+ BTA_FTC_CI_OPEN_EVT, /* Call-in response to File Open request */
+ BTA_FTC_OBX_CONN_RSP_EVT, /* OBX Channel Connect Request */
+ BTA_FTC_OBX_ABORT_RSP_EVT, /* OBX_operation aborted */
+ BTA_FTC_OBX_TOUT_EVT, /* OBX Operation Timeout */
+ BTA_FTC_OBX_PASSWORD_EVT, /* OBX password requested */
+ BTA_FTC_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_FTC_OBX_PUT_RSP_EVT, /* Write file data or delete */
+ BTA_FTC_OBX_GET_RSP_EVT, /* Read file data or folder listing */
+ BTA_FTC_OBX_SETPATH_RSP_EVT, /* Make or Change Directory */
+ BTA_FTC_OBX_CMPL_EVT, /* operation has completed */
+ BTA_FTC_CLOSE_CMPL_EVT, /* Finish the closing of the channel */
+ BTA_FTC_DISABLE_CMPL_EVT, /* Finished disabling system */
+ BTA_FTC_RSP_TOUT_EVT, /* Timeout waiting for response from server */
+
+ /* these events are handled outside the state machine */
+ BTA_FTC_API_ENABLE_EVT
+};
+
+
+/* state machine states */
+enum
+{
+ BTA_FTC_IDLE_ST = 0, /* Idle */
+ BTA_FTC_W4_CONN_ST, /* Waiting for an Obex connect response */
+ BTA_FTC_CONN_ST, /* Connected - FTP Session is active */
+ BTA_FTC_SUSPENDING_ST, /* suspend is in progress */
+ BTA_FTC_CLOSING_ST /* Closing is in progress */
+};
+typedef UINT16 tBTA_FTC_INT_EVT;
+
+typedef UINT8 tBTA_FTC_STATE;
+
+/* Application Parameters Header
+Tag IDs used in the Application Parameters header:
+*/
+ /* Tag ID Length Possible Values */
+#define BTA_FTC_APH_ORDER 0x01 /* Order 1 bytes 0x0 to 0x2 */
+#define BTA_FTC_APH_SEARCH_VALUE 0x02 /* SearchValue variable text */
+#define BTA_FTC_APH_SEARCH_ATTR 0x03 /* SearchAttribute 1 byte 0x0 to 0x2 */
+#define BTA_FTC_APH_MAX_LIST_COUNT 0x04 /* MaxListCount 2 bytes 0x0000 to 0xFFFF */
+#define BTA_FTC_APH_LIST_STOFF 0x05 /* ListStartOffset 2 bytes 0x0000 to 0xFFFF */
+#define BTA_FTC_APH_FILTER 0x06 /* Filter 4 bytes 0x00000000 to 0xFFFFFFFF */
+#define BTA_FTC_APH_FORMAT 0x07 /* Format 1 byte 0x00(2.1), 0x01(3.0) */
+#define BTA_FTC_APH_PB_SIZE 0x08 /* PhoneBookSize 2 byte 0x0000 to 0xFFFF */
+#define BTA_FTC_APH_NEW_MISSED_CALL 0x09 /* NewMissedCall 1 bytes 0x00 to 0xFF */
+#define BTA_FTC_APH_MAX_TAG BTA_FTC_APH_NEW_MISSED_CALL
+
+/* data type for BTA_FTC_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FTC_CBACK *p_cback;
+ UINT8 app_id;
+} tBTA_FTC_API_ENABLE;
+
+/* data type for BTA_FTC_API_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_SERVICE_MASK services; /* FTP and/or OPP */
+ BD_ADDR bd_addr;
+ UINT8 sec_mask;
+ BOOLEAN srm;
+ UINT32 nonce;
+} tBTA_FTC_API_OPEN;
+
+/* data type for BTA_FTC_API_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BOOLEAN suspend;
+} tBTA_FTC_API_CLOSE;
+
+/* data type for BTA_FTC_API_ACTION_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FTC_ACT action;
+ char *p_src; /* UTF-8 name from listing */
+ char *p_dest; /* UTF-8 name */
+ UINT8 permission[3];
+} tBTA_FTC_API_ACTION;
+
+/* data type for BTA_FTC_API_PUTFILE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_name;
+ tBTA_FTC_PARAM *p_param;
+} tBTA_FTC_API_PUT;
+
+typedef struct
+{
+ tBTA_FTC_FILTER_MASK filter;
+ UINT16 max_list_count;
+ UINT16 list_start_offset;
+ tBTA_FTC_FORMAT format;
+} tBTA_FTC_GET_PARAM;
+
+/* data type for BTA_FTC_API_GETFILE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_rem_name; /* UTF-8 name from listing */
+ char *p_name;
+ tBTA_FTC_GET_PARAM *p_param;
+ UINT8 obj_type;
+} tBTA_FTC_API_GET;
+
+/* data type for BTA_FTC_API_CHDIR_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_dir; /* UTF-8 name from listing */
+ tBTA_FTC_FLAG flag;
+} tBTA_FTC_API_CHDIR;
+
+typedef struct
+{
+ char *p_value;
+ UINT16 max_list_count;
+ UINT16 list_start_offset;
+ tBTA_FTC_ORDER order;
+ tBTA_FTC_ATTR attribute;
+} tBTA_FTC_LST_PARAM;
+
+/* data type for BTA_FTC_API_LISTDIR_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_dir; /* UTF-8 name from listing */
+ tBTA_FTC_LST_PARAM *p_param;
+} tBTA_FTC_API_LIST;
+
+/* data type for BTA_FTC_API_MKDIR_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_dir; /* UTF-8 name directory */
+} tBTA_FTC_API_MKDIR;
+
+/* data type for BTA_FTC_API_REMOVE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_name; /* UTF-8 name of file or directory */
+} tBTA_FTC_API_REMOVE;
+
+
+/* data type for BTA_FTC_API_AUTHRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 key [BTA_FTC_MAX_AUTH_KEY_SIZE]; /* The authentication key.*/
+ UINT8 key_len;
+ UINT8 userid [OBX_MAX_REALM_LEN]; /* The authentication user id.*/
+ UINT8 userid_len;
+} tBTA_FTC_API_AUTHRSP;
+
+/* data type for BTA_FTC_SDP_OK_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 scn;
+ UINT16 psm;
+ UINT16 version;
+} tBTA_FTC_SDP_OK_EVT;
+
+/* data type for all obex events
+ hdr.event contains the FTC event
+*/
+typedef struct
+{
+ BT_HDR hdr;
+ tOBX_HANDLE handle;
+ tOBX_EVT_PARAM param;
+ BT_HDR *p_pkt;
+ tOBX_EVENT obx_event;
+ UINT8 rsp_code;
+} tBTA_FTC_OBX_EVT;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_FTC_API_ENABLE api_enable;
+ tBTA_FTC_API_OPEN api_open;
+ tBTA_FTC_API_CLOSE api_close;
+ tBTA_FTC_API_PUT api_put;
+ tBTA_FTC_API_GET api_get;
+ tBTA_FTC_API_CHDIR api_chdir;
+ tBTA_FTC_API_MKDIR api_mkdir;
+ tBTA_FTC_API_REMOVE api_remove;
+ tBTA_FTC_API_AUTHRSP auth_rsp;
+ tBTA_FTC_API_LIST api_list;
+ tBTA_FTC_API_ACTION api_action;
+ tBTA_FTC_SDP_OK_EVT sdp_ok;
+ tBTA_FTC_OBX_EVT obx_evt;
+ tBTA_FS_CI_OPEN_EVT open_evt;
+ tBTA_FS_CI_RESUME_EVT resume_evt;
+ tBTA_FS_CI_READ_EVT read_evt;
+ tBTA_FS_CI_WRITE_EVT write_evt;
+} tBTA_FTC_DATA;
+
+
+/* OBX Response Packet Structure - Holds current command/response packet info */
+typedef struct
+{
+ BT_HDR *p_pkt; /* (Get/Put) Holds the current OBX header for Put or Get */
+ UINT8 *p_start; /* (Get/Put) Start of the Body of the packet */
+ UINT16 offset; /* (Get/Put) Contains the current offset into the Body (p_start) */
+ UINT16 bytes_left; /* (Get/Put) Holds bytes available left in Obx packet */
+ BOOLEAN final_pkt; /* (Get) Holds the final bit of the Put packet */
+} tBTA_FTC_OBX_PKT;
+
+/* Power management state for FTC */
+#define BTA_FTC_PM_BUSY 0
+#define BTA_FTC_PM_IDLE 1
+
+
+/* FTC control block */
+typedef struct
+{
+ tBTA_FTC_CBACK *p_cback; /* pointer to application callback function */
+ char *p_name; /* Holds the local file name */
+ tSDP_DISCOVERY_DB *p_db; /* pointer to discovery database */
+ UINT32 sdp_handle; /* SDP record handle for PCE */
+ tBTA_FTC_OBX_PKT obx; /* Holds the current OBX packet information */
+ TIMER_LIST_ENT rsp_timer; /* response timer */
+ tBTA_SERVICE_MASK services; /* FTP and/or OPP and/or BIP */
+ int fd; /* File Descriptor of opened file */
+ UINT32 file_size; /* (Put/Get) length of file */
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ tBIP_IMAGING_CAPS *p_caps; /* BIP imaging capabilities */
+ tBIP_IMG_HDL_STR img_hdl; /* The image’s handle for when responder requests thumbnail */
+#endif
+ UINT8 *p_sess_info;
+ UINT16 peer_mtu;
+ UINT16 sdp_service;
+ BD_ADDR bd_addr;
+ tOBX_HANDLE obx_handle;
+ UINT8 sec_mask;
+ tBTA_FTC_STATE state; /* state machine state */
+ UINT8 obx_oper; /* current active OBX operation PUT FILE or GET FILE */
+ UINT8 timer_oper; /* current active response timer action (abort or close) */
+ UINT8 app_id;
+ tBTA_FTC_TYPE obj_type; /* type of get op */
+ BOOLEAN first_req_pkt; /* TRUE if retrieving the first packet of GET/PUT file */
+ BOOLEAN cout_active; /* TRUE if call-out is currently active */
+ BOOLEAN disabling; /* TRUE if client is in process of disabling */
+ UINT8 aborting; /* Non-zero if client is in process of aborting */
+ BOOLEAN int_abort; /* TRUE if internal abort issued (Not API inititated) */
+ BOOLEAN is_enabled; /* TRUE if client is enabled */
+ BOOLEAN req_pending; /* TRUE when waiting for an obex response */
+ BOOLEAN sdp_pending; /* TRUE when waiting for SDP to complete */
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ UINT8 bic_handle;
+#endif
+ UINT8 scn;
+ UINT16 version;
+
+ /* OBEX 1.5 */
+ UINT16 psm;
+ UINT32 nonce;
+ BOOLEAN srm;
+ BOOLEAN suspending; /* TRUE when suspending session */
+
+ tBTA_FTC_STATUS status;
+ UINT8 pm_state;
+} tBTA_FTC_CB;
+
+/* type for action functions */
+typedef void (*tBTA_FTC_ACTION)(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+
+/******************************************************************************
+** Configuration Definitions
+*******************************************************************************/
+typedef const tBTA_FTC_ACTION (*tBTA_FTC_BI_TBL);
+
+/* Configuration structure */
+typedef struct
+{
+ tBTA_FTC_BI_TBL p_bi_action; /* BI related action func used in FTC */
+ UINT8 realm_charset; /* Server only */
+ BOOLEAN userid_req; /* TRUE if user id is required during obex authentication (Server only) */
+ BOOLEAN auto_file_list; /* TRUE if automatic get the file listing from sever on OBEX connect response */
+ UINT8 pce_features; /* PBAP PCE supported features. If 0, PCE is not supported */
+ char *pce_name; /* service name for PBAP PCE SDP record */
+ INT32 abort_tout; /* Timeout in milliseconds to wait for abort OBEX response (client only) */
+ INT32 stop_tout; /* Timeout in milliseconds to wait for close OBEX response (client only) */
+ INT32 suspend_tout; /* Timeout in milliseconds to wait for suspend OBEX response (client only) */
+ UINT32 nonce; /* non-0 to allow reliable session (Server Only) */
+ UINT8 max_suspend; /* the maximum number of suspended session (Server Only) */
+ BOOLEAN over_l2cap; /* TRUE to use Obex Over L2CAP (Server Only) */
+ BOOLEAN srm; /* TRUE to engage Single Response Mode (Server Only) */
+
+} tBTA_FT_CFG;
+
+enum
+{
+ BTA_FTC_BI_REGISTER_IDX = 0,
+ BTA_FTC_BI_DEREGISTER_IDX,
+ BTA_FTC_BI_AUTHRSP_IDX,
+ BTA_FTC_BI_FREEXML_IDX,
+ BTA_FTC_BI_PUT_IDX,
+ BTA_FTC_BI_ABORT_IDX
+};
+
+extern const tBTA_FTC_ACTION bta_ftc_bi_action[];
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* FTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_FTC_CB bta_ftc_cb;
+#else
+extern tBTA_FTC_CB *bta_ftc_cb_ptr;
+#define bta_ftc_cb (*bta_ftc_cb_ptr)
+#endif
+
+/* FT configuration constants */
+extern tBTA_FT_CFG *p_bta_ft_cfg;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern BOOLEAN bta_ftc_hdl_event(BT_HDR *p_msg);
+extern void bta_ftc_sm_execute(tBTA_FTC_CB *p_cb, UINT16 event,
+ tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ UINT8 rsp_code, tOBX_EVT_PARAM param,
+ BT_HDR *p_pkt);
+
+extern void bta_ftc_init_open(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_init_close(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_init_putfile(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_init_getfile(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_chdir(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_send_authrsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_abort(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_api_action(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_action_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_get_srm_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_ci_write_srm(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_ci_write(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_ci_read(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_ci_open(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_ci_resume(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_conn_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_sess_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_suspended(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_abort_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_password(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_timeout(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_put_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_get_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_obx_setpath_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_initialize(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_trans_cmpl(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_stop_client(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_start_client(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_free_db(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_ignore_obx(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_find_service(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_close(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_open_fail(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_close_complete(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_set_disable(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_rsp_timeout(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_bic_put(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_bic_abort(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+
+/* BI related action function used in FTC */
+extern void bta_ftc_bic_register(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_bic_deregister(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_bic_authrsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_bic_freexml(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_bic_putact(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_bic_abortact(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+
+
+extern void bta_ftc_listdir(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_remove(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern void bta_ftc_mkdir(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+
+/* miscellaneous functions */
+extern UINT8 bta_ftc_send_get_req(tBTA_FTC_CB *p_cb);
+extern void bta_ftc_proc_get_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data);
+extern UINT8 bta_ftc_cont_put_file(tBTA_FTC_CB *p_cb, BOOLEAN first_pkt);
+extern void bta_ftc_proc_list_data(tBTA_FTC_CB *p_cb, tBTA_FTC_OBX_EVT *p_evt);
+extern void bta_ftc_get_listing(tBTA_FTC_CB *p_cb, char *p_name, tBTA_FTC_LST_PARAM *p_param);
+extern void bta_ftc_listing_err(BT_HDR **p_pkt, tBTA_FTC_STATUS status);
+
+
+extern tBTA_FTC_STATUS bta_ftc_convert_obx_to_ftc_status(tOBX_STATUS obx_status);
+
+#endif /* BTA_FTC_INT_H */
diff --git a/bta/ft/bta_ftc_main.c b/bta/ft/bta_ftc_main.c
new file mode 100644
index 0000000..8148703
--- /dev/null
+++ b/bta/ft/bta_ftc_main.c
@@ -0,0 +1,689 @@
+/*****************************************************************************
+**
+** Name: bta_ftc_main.c
+**
+** Description: This file contains the file transfer client main functions
+** and state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#include <string.h>
+
+#include "bt_target.h"
+
+#if defined(BTA_FT_INCLUDED) && (BTA_FT_INCLUDED == TRUE)
+
+#include "bta_ftc_int.h"
+#include "gki.h"
+#include "obx_api.h"
+
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_FTC_INIT_OPEN,
+ BTA_FTC_START_CLIENT,
+ BTA_FTC_STOP_CLIENT,
+ BTA_FTC_INIT_GETFILE,
+ BTA_FTC_INIT_PUTFILE,
+ BTA_FTC_LISTDIR,
+ BTA_FTC_CHDIR,
+ BTA_FTC_MKDIR,
+ BTA_FTC_REMOVE,
+ BTA_FTC_SEND_AUTHRSP,
+ BTA_FTC_CI_WRITE,
+ BTA_FTC_CI_READ,
+ BTA_FTC_CI_OPEN,
+ BTA_FTC_CI_RESUME,
+ BTA_FTC_OBX_SESS_RSP,
+ BTA_FTC_OBX_GET_SRM_RSP,
+ BTA_FTC_CI_WRITE_SRM,
+ BTA_FTC_SUSPENDED,
+ BTA_FTC_OBX_CONN_RSP,
+ BTA_FTC_CLOSE,
+ BTA_FTC_OPEN_FAIL,
+ BTA_FTC_OBX_ABORT_RSP,
+ BTA_FTC_OBX_PASSWORD,
+ BTA_FTC_OBX_TIMEOUT,
+ BTA_FTC_OBX_PUT_RSP,
+ BTA_FTC_OBX_GET_RSP,
+ BTA_FTC_OBX_SETPATH_RSP,
+ BTA_FTC_TRANS_CMPL,
+ BTA_FTC_FREE_DB,
+ BTA_FTC_IGNORE_OBX,
+ BTA_FTC_FIND_SERVICE,
+ BTA_FTC_INITIALIZE,
+ BTA_FTC_CLOSE_COMPLETE,
+ BTA_FTC_BIC_PUT,
+ BTA_FTC_BIC_ABORT,
+ BTA_FTC_SET_DISABLE,
+ BTA_FTC_ABORT,
+ BTA_FTC_API_ACTION,
+ BTA_FTC_OBX_ACTION_RSP,
+ BTA_FTC_RSP_TIMEOUT,
+ BTA_FTC_IGNORE
+};
+
+/* action function list */
+const tBTA_FTC_ACTION bta_ftc_action[] =
+{
+ bta_ftc_init_open,
+ bta_ftc_start_client,
+ bta_ftc_stop_client,
+ bta_ftc_init_getfile,
+ bta_ftc_init_putfile,
+ bta_ftc_listdir,
+ bta_ftc_chdir,
+ bta_ftc_mkdir,
+ bta_ftc_remove,
+ bta_ftc_send_authrsp,
+ bta_ftc_ci_write,
+ bta_ftc_ci_read,
+ bta_ftc_ci_open,
+ bta_ftc_ci_resume,
+ bta_ftc_obx_sess_rsp,
+ bta_ftc_obx_get_srm_rsp,
+ bta_ftc_ci_write_srm,
+ bta_ftc_suspended,
+ bta_ftc_obx_conn_rsp,
+ bta_ftc_close,
+ bta_ftc_open_fail,
+ bta_ftc_obx_abort_rsp,
+ bta_ftc_obx_password,
+ bta_ftc_obx_timeout,
+ bta_ftc_obx_put_rsp,
+ bta_ftc_obx_get_rsp,
+ bta_ftc_obx_setpath_rsp,
+ bta_ftc_trans_cmpl,
+ bta_ftc_free_db,
+ bta_ftc_ignore_obx,
+ bta_ftc_find_service,
+ bta_ftc_initialize,
+ bta_ftc_close_complete,
+ bta_ftc_bic_put,
+ bta_ftc_bic_abort,
+ bta_ftc_set_disable,
+ bta_ftc_abort,
+ bta_ftc_api_action,
+ bta_ftc_obx_action_rsp,
+ bta_ftc_rsp_timeout
+};
+
+
+/* state table information */
+#define BTA_FTC_ACTIONS 2 /* number of actions */
+#define BTA_FTC_NEXT_STATE 2 /* position of next state */
+#define BTA_FTC_NUM_COLS 3 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_ftc_st_idle[][BTA_FTC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_FTC_API_DISABLE_EVT */ {BTA_FTC_SET_DISABLE, BTA_FTC_INITIALIZE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_OPEN_EVT */ {BTA_FTC_INIT_OPEN, BTA_FTC_FIND_SERVICE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_CLOSE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_PUTFILE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_GETFILE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_LISTDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_CHDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_MKDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_REMOVE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_AUTHRSP_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_ABORT_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_API_ACTION_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_ACTION_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_CI_SESSION_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_SDP_OK_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_SDP_FAIL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_SDP_NEXT_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_CI_WRITE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_CI_READ_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_CI_OPEN_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_CONN_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_ABORT_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_TOUT_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_PASSWORD_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_CLOSE_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_PUT_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_GET_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_SETPATH_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_CLOSE_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_DISABLE_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_RSP_TOUT_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST}
+};
+
+/* state table for wait for authentication response state */
+static const UINT8 bta_ftc_st_w4_conn[][BTA_FTC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_FTC_API_DISABLE_EVT */ {BTA_FTC_SET_DISABLE, BTA_FTC_STOP_CLIENT, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_OPEN_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_CLOSE_EVT */ {BTA_FTC_STOP_CLIENT, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_PUTFILE_EVT */ {BTA_FTC_BIC_PUT, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_GETFILE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_LISTDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_CHDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_MKDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_REMOVE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_AUTHRSP_EVT */ {BTA_FTC_SEND_AUTHRSP, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_ABORT_EVT */ {BTA_FTC_BIC_ABORT, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_API_ACTION_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_OBX_ACTION_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_CI_SESSION_EVT */ {BTA_FTC_CI_RESUME, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_SDP_OK_EVT */ {BTA_FTC_FREE_DB, BTA_FTC_START_CLIENT, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_SDP_FAIL_EVT */ {BTA_FTC_FREE_DB, BTA_FTC_CLOSE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_SDP_NEXT_EVT */ {BTA_FTC_FREE_DB, BTA_FTC_FIND_SERVICE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_CI_WRITE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_CI_READ_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_CI_OPEN_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_OBX_CONN_RSP_EVT */ {BTA_FTC_OBX_CONN_RSP, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_ABORT_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_OBX_TOUT_EVT */ {BTA_FTC_OBX_TIMEOUT, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_OBX_PASSWORD_EVT */ {BTA_FTC_OBX_PASSWORD, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_OBX_CLOSE_EVT */ {BTA_FTC_OPEN_FAIL, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_PUT_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_OBX_GET_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_OBX_SETPATH_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_OBX_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_W4_CONN_ST},
+/* BTA_FTC_CLOSE_CMPL_EVT */ {BTA_FTC_CLOSE_COMPLETE,BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_DISABLE_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_RSP_TOUT_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST}
+
+};
+
+/* state table for connected state */
+static const UINT8 bta_ftc_st_connected[][BTA_FTC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_FTC_API_DISABLE_EVT */ {BTA_FTC_SET_DISABLE, BTA_FTC_STOP_CLIENT, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_OPEN_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_CLOSE_EVT */ {BTA_FTC_STOP_CLIENT, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_PUTFILE_EVT */ {BTA_FTC_INIT_PUTFILE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_GETFILE_EVT */ {BTA_FTC_INIT_GETFILE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_LISTDIR_EVT */ {BTA_FTC_LISTDIR , BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_CHDIR_EVT */ {BTA_FTC_CHDIR, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_MKDIR_EVT */ {BTA_FTC_MKDIR, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_REMOVE_EVT */ {BTA_FTC_REMOVE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_AUTHRSP_EVT */ {BTA_FTC_SEND_AUTHRSP, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_ABORT_EVT */ {BTA_FTC_ABORT, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_API_ACTION_EVT */ {BTA_FTC_API_ACTION, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_ACTION_RSP_EVT */ {BTA_FTC_OBX_ACTION_RSP, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_CI_SESSION_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_SDP_OK_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_SDP_FAIL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_SDP_NEXT_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_CI_WRITE_EVT */ {BTA_FTC_CI_WRITE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_CI_READ_EVT */ {BTA_FTC_CI_READ, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_CI_OPEN_EVT */ {BTA_FTC_CI_OPEN, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_CONN_RSP_EVT */ {BTA_FTC_SUSPENDED, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_ABORT_RSP_EVT */ {BTA_FTC_OBX_ABORT_RSP, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_TOUT_EVT */ {BTA_FTC_OBX_TIMEOUT, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_PASSWORD_EVT */ {BTA_FTC_OBX_PASSWORD, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_CLOSE_EVT */ {BTA_FTC_CLOSE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_PUT_RSP_EVT */ {BTA_FTC_OBX_PUT_RSP, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_GET_RSP_EVT */ {BTA_FTC_OBX_GET_RSP, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_SETPATH_RSP_EVT */ {BTA_FTC_OBX_SETPATH_RSP, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_OBX_CMPL_EVT */ {BTA_FTC_TRANS_CMPL, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_CLOSE_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CONN_ST},
+/* BTA_FTC_DISABLE_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_RSP_TOUT_EVT */ {BTA_FTC_RSP_TIMEOUT, BTA_FTC_IGNORE, BTA_FTC_CONN_ST}
+};
+
+/* state table for suspending state */
+static const UINT8 bta_ftc_st_suspending[][BTA_FTC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_FTC_API_DISABLE_EVT */ {BTA_FTC_SET_DISABLE, BTA_FTC_STOP_CLIENT, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_OPEN_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_CLOSE_EVT */ {BTA_FTC_STOP_CLIENT, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_PUTFILE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_GETFILE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_LISTDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_CHDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_MKDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_REMOVE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_AUTHRSP_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_ABORT_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_API_ACTION_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_OBX_ACTION_RSP_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_CI_SESSION_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_SDP_OK_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_SDP_FAIL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_SDP_NEXT_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_CI_WRITE_EVT */ {BTA_FTC_CI_WRITE_SRM, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_CI_READ_EVT */ {BTA_FTC_CI_READ, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_CI_OPEN_EVT */ {BTA_FTC_CI_OPEN, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_OBX_CONN_RSP_EVT */ {BTA_FTC_OBX_SESS_RSP, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_ABORT_RSP_EVT */ {BTA_FTC_OBX_ABORT_RSP, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_OBX_TOUT_EVT */ {BTA_FTC_OBX_TIMEOUT, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_OBX_PASSWORD_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_OBX_CLOSE_EVT */ {BTA_FTC_CLOSE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_PUT_RSP_EVT */ {BTA_FTC_OBX_PUT_RSP, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_OBX_GET_RSP_EVT */ {BTA_FTC_OBX_GET_SRM_RSP, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_OBX_SETPATH_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_OBX_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_CLOSE_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_SUSPENDING_ST},
+/* BTA_FTC_DISABLE_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_RSP_TOUT_EVT */ {BTA_FTC_RSP_TIMEOUT, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_ftc_st_closing[][BTA_FTC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_FTC_API_DISABLE_EVT */ {BTA_FTC_SET_DISABLE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_OPEN_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_CLOSE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_PUTFILE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_GETFILE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_LISTDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_CHDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_MKDIR_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_REMOVE_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_AUTHRSP_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_ABORT_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_API_ACTION_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_ACTION_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_CI_SESSION_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_SDP_OK_EVT */ {BTA_FTC_FREE_DB, BTA_FTC_CLOSE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_SDP_FAIL_EVT */ {BTA_FTC_FREE_DB, BTA_FTC_CLOSE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_SDP_NEXT_EVT */ {BTA_FTC_FREE_DB, BTA_FTC_CLOSE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_CI_WRITE_EVT */ {BTA_FTC_CLOSE_COMPLETE,BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_CI_READ_EVT */ {BTA_FTC_CLOSE_COMPLETE,BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_CI_OPEN_EVT */ {BTA_FTC_CLOSE_COMPLETE,BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_OBX_CONN_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_ABORT_RSP_EVT */ {BTA_FTC_OBX_ABORT_RSP, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_TOUT_EVT */ {BTA_FTC_OBX_TIMEOUT, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_PASSWORD_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_CLOSE_EVT */ {BTA_FTC_CLOSE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_PUT_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_GET_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_SETPATH_RSP_EVT */ {BTA_FTC_IGNORE_OBX, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_OBX_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_CLOSING_ST},
+/* BTA_FTC_CLOSE_CMPL_EVT */ {BTA_FTC_CLOSE_COMPLETE,BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_DISABLE_CMPL_EVT */ {BTA_FTC_IGNORE, BTA_FTC_IGNORE, BTA_FTC_IDLE_ST},
+/* BTA_FTC_RSP_TOUT_EVT */ {BTA_FTC_RSP_TIMEOUT, BTA_FTC_CLOSE_COMPLETE, BTA_FTC_IDLE_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_FTC_ST_TBL)[BTA_FTC_NUM_COLS];
+
+/* state table */
+const tBTA_FTC_ST_TBL bta_ftc_st_tbl[] =
+{
+ bta_ftc_st_idle,
+ bta_ftc_st_w4_conn,
+ bta_ftc_st_connected,
+ bta_ftc_st_suspending,
+ bta_ftc_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* FTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_FTC_CB bta_ftc_cb;
+#endif
+
+#if BTA_FTC_DEBUG == TRUE
+static char *ftc_evt_code(tBTA_FTC_INT_EVT evt_code);
+static char *ftc_state_code(tBTA_FTC_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ftc_sm_execute
+**
+** Description State machine event handling function for FTC
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_sm_execute(tBTA_FTC_CB *p_cb, UINT16 event, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_ST_TBL state_table;
+ UINT8 action;
+ int i;
+#if BTA_FTC_DEBUG == TRUE
+ tBTA_FTC_STATE in_state = p_cb->state;
+ UINT16 in_event = event;
+ APPL_TRACE_DEBUG4("bta_ftc_sm_execute: State 0x%02x [%s], Event 0x%x[%s]", in_state,
+ ftc_state_code(in_state),
+ in_event,
+ ftc_evt_code(in_event));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_ftc_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_FTC_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_FTC_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_FTC_IGNORE)
+ {
+ (*bta_ftc_action[action])(p_cb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+#if BTA_FTC_DEBUG == TRUE
+ if (in_state != p_cb->state)
+ {
+ APPL_TRACE_DEBUG3("FTC State Change: [%s] -> [%s] after Event [%s]",
+ ftc_state_code(in_state),
+ ftc_state_code(p_cb->state),
+ ftc_evt_code(in_event));
+ }
+#endif
+}
+
+/*****************************************************************************
+**
+** Function: bta_ftc_sdp_register()
+**
+** Purpose: Registers the File Transfer service with SDP
+**
+** Parameters:
+**
+**
+** Returns: void
+**
+*****************************************************************************/
+static void bta_ftc_sdp_register (tBTA_FTC_CB *p_cb)
+{
+ UINT16 pbap_service = UUID_SERVCLASS_PBAP_PCE;
+ UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+ BOOLEAN status = FALSE;
+
+ if ((p_cb->sdp_handle = SDP_CreateRecord()) == 0)
+ {
+ APPL_TRACE_WARNING0("FTC SDP: Unable to register PBAP PCE Service");
+ return;
+ }
+
+ /* add service class */
+ if (SDP_AddServiceClassIdList(p_cb->sdp_handle, 1, &pbap_service))
+ {
+ status = TRUE; /* All mandatory fields were successful */
+
+ /* optional: if name is not "", add a name entry */
+ if (p_bta_ft_cfg->pce_name && p_bta_ft_cfg->pce_name[0] != '\0')
+ SDP_AddAttribute(p_cb->sdp_handle,
+ (UINT16)ATTR_ID_SERVICE_NAME,
+ (UINT8)TEXT_STR_DESC_TYPE,
+ (UINT32)(strlen(p_bta_ft_cfg->pce_name) + 1),
+ (UINT8 *)p_bta_ft_cfg->pce_name);
+
+ /* Add in the Bluetooth Profile Descriptor List */
+ SDP_AddProfileDescriptorList(p_cb->sdp_handle,
+ UUID_SERVCLASS_PBAP_PCE,
+ BTA_FTC_DEFAULT_VERSION);
+ } /* end of setting mandatory service class */
+
+ /* Make the service browseable */
+ SDP_AddUuidSequence (p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
+
+ if (!status)
+ {
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ APPL_TRACE_ERROR0("bta_ftc_sdp_register FAILED");
+ p_cb->sdp_handle = 0;
+ }
+ else
+ {
+ bta_sys_add_uuid( pbap_service ); /* UUID_SERVCLASS_PBAP_PCE */
+ APPL_TRACE_DEBUG1("FTC: SDP Registered (handle 0x%08x)", p_cb->sdp_handle);
+ }
+
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_api_enable
+**
+** Description Handle an api enable event. This function enables the FT
+** Client by opening an Obex/Rfcomm channel with a peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ftc_api_enable(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ if (!p_cb->is_enabled)
+ {
+ /* initialize control block */
+ memset(p_cb, 0, sizeof(tBTA_FTC_CB));
+
+ /* store parameters */
+ p_cb->p_cback = p_data->api_enable.p_cback;
+ p_cb->app_id = p_data->api_enable.app_id;
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ p_cb->bic_handle = BTA_BIC_INVALID_HANDLE;
+#endif
+ p_cb->fd = BTA_FS_INVALID_FD;
+ p_cb->is_enabled = TRUE;
+
+ /* create SDP record for PCE */
+ if(p_bta_ft_cfg->pce_features)
+ bta_ftc_sdp_register(p_cb);
+ }
+
+ /* callback with enable event */
+ (*p_cb->p_cback)(BTA_FTC_ENABLE_EVT, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_hdl_event
+**
+** Description File transfer server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_ftc_hdl_event(BT_HDR *p_msg)
+{
+ tBTA_FTC_CB *p_cb = &bta_ftc_cb;
+#if BTA_FTC_DEBUG == TRUE
+ tBTA_FTC_STATE in_state = p_cb->state;
+#endif
+
+ switch (p_msg->event)
+ {
+ case BTA_FTC_API_ENABLE_EVT:
+#if BTA_FTC_DEBUG == TRUE
+ APPL_TRACE_DEBUG3("FTC Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ ftc_state_code(in_state),
+ ftc_evt_code(p_msg->event));
+#endif
+ bta_ftc_api_enable(p_cb, (tBTA_FTC_DATA *) p_msg);
+#if BTA_FTC_DEBUG == TRUE
+ if (in_state != p_cb->state)
+ {
+ APPL_TRACE_DEBUG3("FTC State Change: [%s] -> [%s] after Event [%s]",
+ ftc_state_code(in_state),
+ ftc_state_code(p_cb->state),
+ ftc_evt_code(p_msg->event));
+ }
+#endif
+ break;
+
+ default:
+ if (p_cb->is_enabled)
+ {
+ bta_ftc_sm_execute(p_cb, p_msg->event, (tBTA_FTC_DATA *) p_msg);
+
+ if ( p_cb->state == BTA_FTC_CONN_ST )
+ {
+ if (( p_cb->pm_state == BTA_FTC_PM_IDLE )
+ &&( p_cb->obx_oper != FTC_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA FTC informs DM/PM busy state");
+ bta_sys_busy( BTA_ID_FTC, p_cb->app_id, p_cb->bd_addr );
+ p_cb->pm_state = BTA_FTC_PM_BUSY;
+ }
+ else if (( p_cb->pm_state == BTA_FTC_PM_BUSY )
+ &&( p_cb->obx_oper == FTC_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA FTC informs DM/PM idle state");
+ bta_sys_idle( BTA_ID_FTC ,p_cb->app_id, p_cb->bd_addr);
+ p_cb->pm_state = BTA_FTC_PM_IDLE;
+ }
+ }
+ else if ( p_cb->state == BTA_FTC_IDLE_ST )
+ {
+ /* initialize power management state */
+ p_cb->pm_state = BTA_FTC_PM_BUSY;
+ }
+ }
+ break;
+ }
+
+
+ return (TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_FTC_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function ftc_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ftc_evt_code(tBTA_FTC_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_FTC_API_DISABLE_EVT:
+ return "BTA_FTC_API_DISABLE_EVT";
+ case BTA_FTC_API_OPEN_EVT:
+ return "BTA_FTC_API_OPEN_EVT";
+ case BTA_FTC_API_CLOSE_EVT:
+ return "BTA_FTC_API_CLOSE_EVT";
+ case BTA_FTC_API_PUTFILE_EVT:
+ return "BTA_FTC_API_PUTFILE_EVT";
+ case BTA_FTC_API_GETFILE_EVT:
+ return "BTA_FTC_API_GETFILE_EVT";
+ case BTA_FTC_API_LISTDIR_EVT:
+ return "BTA_FTC_API_LISTDIR_EVT";
+ case BTA_FTC_API_CHDIR_EVT:
+ return "BTA_FTC_API_CHDIR_EVT";
+ case BTA_FTC_API_MKDIR_EVT:
+ return "BTA_FTC_API_MKDIR_EVT";
+ case BTA_FTC_API_REMOVE_EVT:
+ return "BTA_FTC_API_REMOVE_EVT";
+ case BTA_FTC_API_AUTHRSP_EVT:
+ return "BTA_FTC_API_AUTHRSP_EVT";
+ case BTA_FTC_API_ABORT_EVT:
+ return "BTA_FTC_API_ABORT_EVT";
+ case BTA_FTC_API_ACTION_EVT:
+ return "BTA_FTC_API_ACTION_EVT";
+ case BTA_FTC_OBX_ACTION_RSP_EVT:
+ return "BTA_FTC_OBX_ACTION_RSP_EVT";
+ case BTA_FTC_CI_SESSION_EVT:
+ return "BTA_FTC_CI_SESSION_EVT";
+ case BTA_FTC_SDP_OK_EVT:
+ return "BTA_FTC_SDP_OK_EVT";
+ case BTA_FTC_SDP_FAIL_EVT:
+ return "BTA_FTC_SDP_FAIL_EVT";
+ case BTA_FTC_SDP_NEXT_EVT:
+ return "BTA_FTC_SDP_NEXT_EVT";
+ case BTA_FTC_CI_WRITE_EVT:
+ return "BTA_FTC_CI_WRITE_EVT";
+ case BTA_FTC_CI_READ_EVT:
+ return "BTA_FTC_CI_READ_EVT";
+ case BTA_FTC_CI_OPEN_EVT:
+ return "BTA_FTC_CI_OPEN_EVT";
+ case BTA_FTC_OBX_CONN_RSP_EVT:
+ return "BTA_FTC_OBX_CONN_RSP_EVT";
+ case BTA_FTC_OBX_ABORT_RSP_EVT:
+ return "BTA_FTC_OBX_ABORT_RSP_EVT";
+ case BTA_FTC_OBX_TOUT_EVT:
+ return "BTA_FTC_OBX_TOUT_EVT";
+ case BTA_FTC_OBX_PASSWORD_EVT:
+ return "BTA_FTC_OBX_PASSWORD_EVT";
+ case BTA_FTC_OBX_CLOSE_EVT:
+ return "BTA_FTC_OBX_CLOSE_EVT";
+ case BTA_FTC_OBX_PUT_RSP_EVT:
+ return "BTA_FTC_OBX_PUT_RSP_EVT";
+ case BTA_FTC_CLOSE_CMPL_EVT:
+ return "BTA_FTC_CLOSE_CMPL_EVT";
+ case BTA_FTC_OBX_GET_RSP_EVT:
+ return "BTA_FTC_OBX_GET_RSP_EVT";
+ case BTA_FTC_OBX_SETPATH_RSP_EVT:
+ return "BTA_FTC_OBX_SETPATH_RSP_EVT";
+ case BTA_FTC_OBX_CMPL_EVT:
+ return "BTA_FTC_OBX_CMPL_EVT";
+ case BTA_FTC_DISABLE_CMPL_EVT:
+ return "BTA_FTC_DISABLE_CMPL_EVT";
+ case BTA_FTC_RSP_TOUT_EVT:
+ return "BTA_FTC_RSP_TOUT_EVT";
+ case BTA_FTC_API_ENABLE_EVT:
+ return "BTA_FTC_API_ENABLE_EVT";
+ default:
+ return "unknown FTC event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function ftc_state_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ftc_state_code(tBTA_FTC_STATE state_code)
+{
+ switch(state_code)
+ {
+ case BTA_FTC_IDLE_ST:
+ return "BTA_FTC_IDLE_ST";
+ case BTA_FTC_W4_CONN_ST:
+ return "BTA_FTC_W4_CONN_ST";
+ case BTA_FTC_CONN_ST:
+ return "BTA_FTC_CONN_ST";
+ case BTA_FTC_SUSPENDING_ST:
+ return "BTA_FTC_SUSPENDING_ST";
+ case BTA_FTC_CLOSING_ST:
+ return "BTA_FTC_CLOSING_ST";
+ default:
+ return "unknown FTC state code";
+ }
+}
+
+#endif /* Debug Functions */
+#endif /* BTA_FT_INCLUDED */
diff --git a/bta/ft/bta_ftc_utils.c b/bta/ft/bta_ftc_utils.c
new file mode 100644
index 0000000..8468d5f
--- /dev/null
+++ b/bta/ft/bta_ftc_utils.c
@@ -0,0 +1,608 @@
+/*****************************************************************************
+**
+** Name: bta_ftc_utils.c
+**
+** Description: This file implements object store functions for the
+** file transfer server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+
+#if defined(BTA_FT_INCLUDED) && (BTA_FT_INCLUDED == TRUE)
+
+#include <stdio.h>
+#include <string.h>
+#include "bta_ftc_int.h"
+#include "bta_fs_api.h"
+#include "bta_fs_co.h"
+#include "gki.h"
+#include "utl.h"
+
+/*******************************************************************************
+** Constants
+*******************************************************************************/
+
+/*******************************************************************************
+** Local Function Prototypes
+*******************************************************************************/
+
+/*******************************************************************************
+* Macros for FTC
+*******************************************************************************/
+#define BTA_FTC_XML_EOL "\n"
+#define BTA_FTC_FOLDER_LISTING_START ( "<?xml version=\"1.0\"?>\n" \
+ "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">\n" \
+ "<folder-listing version=\"1.0\">\n" )
+
+#define BTA_FTC_FOLDER_LISTING_END ( "</folder-listing>" )
+
+#define BTA_FTC_FILE_ELEM "file"
+#define BTA_FTC_FOLDER_ELEM "folder"
+#define BTA_FTC_PARENT_FOLDER_ELEM "parent-folder"
+#define BTA_FTC_NAME_ATTR "name"
+#define BTA_FTC_SIZE_ATTR "size"
+#define BTA_FTC_TYPE_ATTR "type"
+#define BTA_FTC_MODIFIED_ATTR "modified"
+#define BTA_FTC_CREATED_ATTR "created"
+#define BTA_FTC_ACCESSED_ATTR "accessed"
+#define BTA_FTC_USER_PERM_ATTR "user-perm"
+#define BTA_FTC_GROUP_PERM_ATTR "group-perm"
+#define BTA_FTC_OTHER_PERM_ATTR "other-perm"
+#define BTA_FTC_GROUP_ATTR "group"
+#define BTA_FTC_OWNER_ATTR "owner"
+#define BTA_FTC_LANG_ATTR "xml:lang"
+
+/*******************************************************************************
+** Local Function
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ftc_send_abort_req
+**
+** Description Send an abort request.
+**
+** Parameters p_cb - Pointer to the FTC control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_send_abort_req(tBTA_FTC_CB *p_cb)
+{
+ if (FTC_ABORT_REQ_NOT_SENT == p_cb->aborting)
+ {
+ p_cb->aborting = FTC_ABORT_REQ_SENT;
+ OBX_AbortReq(p_cb->obx_handle, (BT_HDR *)NULL);
+
+ /* Start abort response timer */
+ p_cb->timer_oper = FTC_TIMER_OP_ABORT;
+ bta_sys_start_timer(&p_cb->rsp_timer, BTA_FTC_RSP_TOUT_EVT,
+ p_bta_ft_cfg->abort_tout);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_ftc_proc_pbap_param
+**
+** Description read PBAP app parameter header.
+**
+** Parameters
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_FTC_PB_PARAM * bta_ftc_proc_pbap_param(tBTA_FTC_PB_PARAM *p_param, BT_HDR *p_pkt)
+{
+ UINT8 *p_data = NULL, aph;
+ UINT16 data_len = 0;
+ int left, len;
+ if(OBX_ReadByteStrHdr(p_pkt, OBX_HI_APP_PARMS, &p_data, &data_len, 0))
+ {
+ memset(p_param, 0, sizeof(tBTA_FTC_PB_PARAM));
+ left = data_len;
+ while(left > 0)
+ {
+ aph = *p_data++;
+ len = *p_data++;
+ left -= len;
+ left -= 2;
+ switch(aph)
+ {
+ case BTA_FTC_APH_PB_SIZE:
+ BE_STREAM_TO_UINT16(p_param->phone_book_size, p_data);
+ p_param->pbs_exist = TRUE;
+ break;
+ case BTA_FTC_APH_NEW_MISSED_CALL:
+ p_param->new_missed_calls = *p_data++;
+ p_param->nmc_exist = TRUE;
+ break;
+ default:
+ p_data += len;
+ }
+ }
+ }
+ else
+ p_param = NULL;
+ return p_param;
+}
+
+/*******************************************************************************
+* Exported Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ftc_send_get_req
+**
+** Description Processes a Get File Operation.
+**
+** Parameters p_cb - Pointer to the FTC control block
+**
+** Returns (UINT8) OBX response code
+**
+*******************************************************************************/
+UINT8 bta_ftc_send_get_req(tBTA_FTC_CB *p_cb)
+{
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ /* Do not start another request if currently aborting */
+ if (!p_cb->aborting)
+ {
+ /* OBX header are added in bta_ftc_init_getfile */
+ if ((OBX_GetReq(p_cb->obx_handle, TRUE, p_obx->p_pkt)) == OBX_SUCCESS)
+ {
+ p_cb->req_pending = TRUE;
+ rsp_code = OBX_RSP_OK;
+ p_obx->p_pkt = NULL;
+ }
+ }
+ else
+ {
+ bta_ftc_send_abort_req(p_cb);
+ }
+
+ return (rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_proc_get_rsp
+**
+** Description Processes a Get File response packet.
+** Initiates a file write if no errors.
+**
+** Parameters
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_proc_get_rsp(tBTA_FTC_CB *p_cb, tBTA_FTC_DATA *p_data)
+{
+ tBTA_FTC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 body_size;
+ BOOLEAN final;
+ BOOLEAN done = TRUE;
+ BOOLEAN send_request = TRUE;
+ UINT8 num_hdrs;
+ tBTA_FTC data;
+
+ do
+ {
+ if (p_evt->rsp_code == OBX_RSP_OK || p_evt->rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* Only continue if not aborting */
+ if (p_cb->aborting)
+ {
+ /* Aborting: done with current packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ /* If aborting, and this response is not last packet send abort */
+ if(p_evt->rsp_code == OBX_RSP_CONTINUE)
+ {
+ bta_ftc_send_abort_req(p_cb);
+ return;
+ }
+ else /* Last packet - abort and remove file (p_evt->rsp_code == OBX_RSP_OK) */
+ {
+ p_evt->rsp_code = (!p_cb->int_abort) ? OBX_RSP_GONE : OBX_RSP_INTRNL_SRVR_ERR;
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ return;
+ }
+ }
+
+ p_obx->final_pkt = (p_evt->rsp_code == OBX_RSP_OK) ? TRUE : FALSE;
+
+ /* If length header exists, save the file length */
+ if (p_cb->first_req_pkt == TRUE)
+ {
+ p_cb->first_req_pkt = FALSE;
+
+ /* if the obj_type is */
+ if(p_cb->obj_type == BTA_FTC_GET_PB)
+ {
+ bta_ftc_proc_pbap_param(&data.pb, p_obx->p_pkt);
+ bta_ftc_cb.p_cback(BTA_FTC_PHONEBOOK_EVT, &data);
+ if (p_cb->fd == BTA_FS_INVALID_FD)
+ {
+ /* if the obj_type is get pb && the file id not open,
+ * must be getting the phonebook size only
+ * - end of transaction */
+ break;
+ }
+ }
+ if (!OBX_ReadLengthHdr(p_evt->p_pkt, &p_cb->file_size))
+ p_cb->file_size = BTA_FS_LEN_UNKNOWN;
+ }
+
+ /* Read the body header from the obx packet */
+ num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &body_size,
+ &final);
+ /* process body header */
+ if (num_hdrs == 1)
+ {
+ if (body_size)
+ {
+ /* Data to be written */
+ p_obx->p_pkt = p_evt->p_pkt;
+ p_obx->offset = body_size; /* Save write size for comparison */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, p_obx->p_start, body_size,
+ BTA_FTC_CI_WRITE_EVT, 0, p_cb->app_id);
+ done = FALSE;
+ send_request = FALSE;
+ }
+ /* If body header is zero in length but not final, request next packet */
+ else if (!final)
+ {
+ done = FALSE;
+ }
+ }
+ else if (num_hdrs > 1) /* Cannot handle more than a single body header */
+ {
+ p_evt->rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ /* Empty Body; send next request or finished */
+ else if (!p_obx->final_pkt)
+ done = FALSE;
+ }
+ } while (0);
+
+ if (done)
+ {
+ bta_ftc_sm_execute(p_cb, BTA_FTC_OBX_CMPL_EVT, p_data);
+ utl_freebuf((void**)&p_evt->p_pkt);
+ }
+ else if (send_request)
+ {
+ /* Free current packet and send a new request */
+ utl_freebuf((void**)&p_evt->p_pkt);
+ bta_ftc_send_get_req(p_cb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_cont_put_file
+**
+** Description Continues a Put File Operation.
+** Builds a new OBX packet, and initiates a read operation.
+**
+** Parameters p_cb - pointer to the client's control block.
+** first_pkt - TRUE if initial PUT request to server.
+**
+**
+** Returns UINT8 OBX response code
+**
+*******************************************************************************/
+UINT8 bta_ftc_cont_put_file(tBTA_FTC_CB *p_cb, BOOLEAN first_pkt)
+{
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code;
+ char *p_ch;
+
+ /* Do not start another request if currently aborting */
+ if (p_cb->aborting)
+ {
+ bta_ftc_send_abort_req(p_cb);
+ return (OBX_RSP_OK);
+ }
+
+ rsp_code = OBX_RSP_FAILED;
+
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, p_cb->peer_mtu)) != NULL)
+ {
+ p_obx->offset = 0;
+
+ /* Add length header if it exists; No body in first packet */
+ if (first_pkt)
+ {
+ /* Add the Name Header to the request */
+ /* Find the beginning of the name (excluding the path) */
+ p_ch = strrchr(p_cb->p_name, (int) p_bta_fs_cfg->path_separator);
+ if (p_ch && p_ch[1] != '\0')
+ {
+ OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)&p_ch[1]);
+
+ /* Add the length header if known */
+ if (p_cb->file_size != BTA_FS_LEN_UNKNOWN)
+ {
+ OBX_AddLengthHdr(p_obx->p_pkt, p_cb->file_size);
+
+ }
+
+ OBX_PutReq(p_cb->obx_handle, FALSE, p_obx->p_pkt);
+ p_cb->req_pending = TRUE;
+ p_obx->p_pkt = NULL;
+ rsp_code = OBX_RSP_OK;
+ }
+ }
+ else /* A continuation packet so read file data */
+ {
+ /* Add the start of the Body Header */
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ /* Read in the first packet's worth of data */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_read(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_FTC_CI_READ_EVT, 0, p_cb->app_id);
+ rsp_code = OBX_RSP_OK;
+ }
+ }
+
+ return (rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_proc_list_data
+**
+** Description Processes responses to directory listing requests
+** Loops through returned data generating application
+** listing data events. If needed, issues a new request
+** to the server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_proc_list_data(tBTA_FTC_CB *p_cb, tBTA_FTC_OBX_EVT *p_evt)
+{
+ tBTA_FTC app_evt;
+ tBTA_FTC_PB_PARAM param;
+ BOOLEAN is_ok = FALSE;
+ BOOLEAN first_req_pkt = p_cb->first_req_pkt;
+
+ app_evt.list.status = bta_ftc_convert_obx_to_ftc_status(p_evt->rsp_code);
+
+ if (p_evt->rsp_code == OBX_RSP_OK || p_evt->rsp_code == OBX_RSP_CONTINUE)
+ {
+ app_evt.list.p_param = NULL;
+ if (p_cb->first_req_pkt == TRUE)
+ {
+ p_cb->first_req_pkt = FALSE;
+ if(p_cb->sdp_service == UUID_SERVCLASS_PBAP_PSE)
+ app_evt.list.p_param = bta_ftc_proc_pbap_param(&param, p_evt->p_pkt);
+ }
+ APPL_TRACE_EVENT1("first_req_pkt: %d ", first_req_pkt);
+
+ if (OBX_ReadBodyHdr(p_evt->p_pkt, &app_evt.list.data, &app_evt.list.len,
+ &app_evt.list.final))
+ {
+ /* len > 0 or is final packet */
+ if(app_evt.list.len || app_evt.list.final)
+
+ {
+ bta_ftc_cb.p_cback(BTA_FTC_LIST_EVT, &app_evt);
+ }
+ is_ok = TRUE;
+ }
+ else if(first_req_pkt && p_evt->rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* no body header is OK, if this is the first packet and is continue response */
+ is_ok = TRUE;
+ }
+
+ if(is_ok)
+ {
+ utl_freebuf((void**)&p_evt->p_pkt);
+ /* Initiate another request if not finished */
+ if (p_evt->rsp_code == OBX_RSP_CONTINUE)
+ {
+ if (p_cb->aborting)
+ bta_ftc_send_abort_req(p_cb);
+ else
+ bta_ftc_get_listing(p_cb, NULL, NULL);
+ }
+ else
+ p_cb->obx_oper = FTC_OP_NONE; /* Finished with directory listing */
+ }
+ else
+ {
+ /* Missing body header & not the first packet */
+ bta_ftc_listing_err(&p_evt->p_pkt, OBX_RSP_NO_CONTENT);
+ }
+ }
+ else /* Issue an error list entry */
+ bta_ftc_listing_err(&p_evt->p_pkt, app_evt.list.status);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_get_listing
+**
+** Description Initiates or Continues a GET Listing operation
+** on the server's current directory.
+**
+** Parameters p_cb - pointer to the client's control block.
+** first_pkt - TRUE if initial GET request to server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_get_listing(tBTA_FTC_CB *p_cb, char *p_name, tBTA_FTC_LST_PARAM *p_param)
+{
+ tBTA_FTC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTC_STATUS status = BTA_FTC_FAIL;
+ BOOLEAN is_ok = TRUE;
+ UINT8 *p, *p2, *p_start;
+ UINT16 len = 0;
+
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, OBX_CMD_POOL_SIZE)) != NULL)
+ {
+ if (p_name)
+ {
+ /* first packet */
+ p_cb->first_req_pkt = TRUE;
+ /* Add the Type Header */
+ p = (UINT8 *) BTA_FTC_FOLDER_LISTING_TYPE;
+ if(p_cb->sdp_service == UUID_SERVCLASS_PBAP_PSE)
+ p = (UINT8 *) BTA_FTC_PULL_VCARD_LISTING_TYPE;
+
+ is_ok = OBX_AddTypeHdr(p_obx->p_pkt, (char *)p);
+
+ if(strcmp(p_name, ".") == 0 || p_name[0] == 0)
+ {
+ p_name = NULL;
+ }
+
+ if (p_name)
+ {
+ is_ok = OBX_AddUtf8NameHdr(p_obx->p_pkt, (unsigned char *) p_name);
+ }
+
+ if(p_param && p_cb->sdp_service == UUID_SERVCLASS_PBAP_PSE)
+ {
+ /* add app params for PCE */
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ p = p_start;
+ if(p_param->order < BTA_FTC_ORDER_MAX)
+ {
+ *p++ = BTA_FTC_APH_ORDER;
+ *p++ = 1;
+ *p++ = p_param->order;
+ }
+ if(p_param->p_value)
+ {
+ *p++ = BTA_FTC_APH_SEARCH_VALUE;
+ *p = strlen(p_param->p_value);
+ BCM_STRNCPY_S((char *) (p+1), strlen(p_param->p_value), p_param->p_value, *p);
+ p2 = p + 1 + *p;
+ p = p2;
+ }
+ if(p_param->attribute < BTA_FTC_ATTR_MAX)
+ {
+ *p++ = BTA_FTC_APH_SEARCH_ATTR;
+ *p++ = 1;
+ *p++ = p_param->attribute;
+ }
+ if(p_param->max_list_count != 0xFFFF)
+ {
+ *p++ = BTA_FTC_APH_MAX_LIST_COUNT;
+ *p++ = 2;
+ UINT16_TO_BE_STREAM(p, p_param->max_list_count);
+ }
+ if(p_param->list_start_offset)
+ {
+ *p++ = BTA_FTC_APH_LIST_STOFF;
+ *p++ = 2;
+ UINT16_TO_BE_STREAM(p, p_param->list_start_offset);
+ }
+
+ /* If any of the app param header is added */
+ if(p != p_start)
+ {
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+ } /* if p_param: PBAP PCE need to keep AppParam in the first Get response */
+ }
+
+ if (is_ok)
+ {
+ if ((OBX_GetReq(p_cb->obx_handle, TRUE, p_obx->p_pkt)) == OBX_SUCCESS)
+ {
+ p_cb->req_pending = TRUE;
+ p_obx->p_pkt = NULL; /* OBX will free the memory */
+ p_cb->obx_oper = FTC_OP_GET_LIST;
+ status = BTA_FTC_OK;
+ }
+ }
+ }
+
+ if (status != BTA_FTC_OK) /* Send an error response to the application */
+ bta_ftc_listing_err(&p_obx->p_pkt, status);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_listing_err
+**
+** Description Send a directory listing error event to the application
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ftc_listing_err(BT_HDR **p_pkt, tBTA_FTC_STATUS status)
+{
+ tBTA_FTC err_rsp;
+
+ if (bta_ftc_cb.obx_oper == FTC_OP_GET_LIST)
+ bta_ftc_cb.obx_oper = FTC_OP_NONE;
+ utl_freebuf((void**)p_pkt);
+
+ err_rsp.list.len = 0;
+ err_rsp.list.status = status;
+ err_rsp.list.final = TRUE;
+ err_rsp.list.data = NULL;
+ bta_ftc_cb.p_cback(BTA_FTC_LIST_EVT, &err_rsp);
+}
+
+/*******************************************************************************
+**
+** Function bta_ftc_convert_obx_to_ftc_status
+**
+** Description Convert OBX response code into BTA FTC status code.
+**
+** Returns void
+**
+*******************************************************************************/
+tBTA_FTC_STATUS bta_ftc_convert_obx_to_ftc_status(tOBX_STATUS obx_status)
+{
+ tBTA_FTC_STATUS status;
+
+ switch (obx_status)
+ {
+ case OBX_RSP_OK:
+ case OBX_RSP_CONTINUE:
+ status = BTA_FTC_OK;
+ break;
+ case OBX_RSP_UNAUTHORIZED:
+ status = BTA_FTC_NO_PERMISSION;
+ break;
+ case OBX_RSP_NOT_FOUND:
+ status = BTA_FTC_NOT_FOUND;
+ break;
+ case OBX_RSP_REQ_ENT_2_LARGE:
+ case OBX_RSP_DATABASE_FULL:
+ status = BTA_FTC_FULL;
+ break;
+ case OBX_RSP_GONE:
+ status = BTA_FTC_ABORTED;
+ break;
+ case OBX_RSP_SERVICE_UNAVL:
+ status = BTA_FTC_SERVICE_UNAVL;
+ break;
+ default:
+ status = BTA_FTC_FAIL;
+ }
+
+ return (status);
+}
+#endif /* BTA_FT_INCLUDED */
diff --git a/bta/ft/bta_fts_act.c b/bta/ft/bta_fts_act.c
new file mode 100644
index 0000000..52ba9e4
--- /dev/null
+++ b/bta/ft/bta_fts_act.c
@@ -0,0 +1,1523 @@
+/*****************************************************************************
+**
+** Name: bta_fts_act.c
+**
+** Description: This file contains the file transfer action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_FT_INCLUDED) && (BTA_FT_INCLUDED == TRUE)
+
+#include <stdio.h>
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_ft_api.h"
+#include "bta_fts_int.h"
+#include "bta_fs_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#include "btm_api.h"
+#include "utl.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+#define FLAGS_ARE_MASK (OBX_SPF_BACKUP | OBX_SPF_NO_CREATE)
+#define FLAGS_ARE_ILLEGAL 0x1 /* 'Backup and Create flag combo is BAD */
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if BTA_FTS_DEBUG == TRUE
+static char *fts_obx_evt_code(tOBX_EVENT evt_code);
+#endif
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_fts_api_disable
+**
+** Description Stop FTP server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_api_disable(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+
+ /* If callout is active, wait till finished before shutting down */
+ if (p_cb->cout_active)
+ p_cb->disabling = TRUE;
+ else
+ bta_fts_sm_execute(p_cb, BTA_FTS_DISABLE_CMPL_EVT, p_data);
+
+ bta_sys_remove_uuid(UUID_SERVCLASS_OBEX_FILE_TRANSFER);
+ BTM_SecClrService(BTM_SEC_SERVICE_OBEX_FTP);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_api_authrsp
+**
+** Description Pass the response to an authentication request back to the
+** client.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_api_authrsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ UINT8 *p_pwd = NULL;
+ UINT8 *p_userid = NULL;
+
+ if (p_data->auth_rsp.key_len > 0)
+ p_pwd = (UINT8 *)p_data->auth_rsp.key;
+ if (p_data->auth_rsp.userid_len > 0)
+ p_userid = (UINT8 *)p_data->auth_rsp.userid;
+
+ OBX_Password(p_cb->obx_handle, p_pwd, p_data->auth_rsp.key_len,
+ p_userid, p_data->auth_rsp.userid_len);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_api_accessrsp
+**
+** Description Process the access API event.
+** If permission had been granted, continue the PUT operation,
+** otherwise stop the operation.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_api_accessrsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ UINT8 rsp_code = OBX_RSP_OK;
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_EACCES;
+ tBTA_FT_ACCESS access = p_data->access_rsp.flag;
+ tBTA_FT_OPER old_acc_active = p_cb->acc_active;
+ tBTA_FTS_OBX_RSP *p_rsp = NULL;
+ tBTA_FTS_OBJECT objevt;
+
+ APPL_TRACE_DEBUG3("bta_fts_api_accessrsp op:%d/%d access:%d", old_acc_active, p_data->access_rsp.oper, access);
+ if(p_cb->acc_active != p_data->access_rsp.oper )
+ {
+ APPL_TRACE_WARNING2("FTS ACCRSP: not match active:%d, rsp:%d",
+ p_cb->acc_active, p_data->access_rsp.oper);
+ return;
+ }
+
+ p_cb->acc_active = 0;
+ /* Process the currently active access response */
+ switch (old_acc_active)
+ {
+ case BTA_FT_OPER_PUT:
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ /* Save the file name with path prepended */
+ BCM_STRNCPY_S(p_cb->p_path, p_bta_fs_cfg->max_file_len+1, p_data->access_rsp.p_name, p_bta_fs_cfg->max_file_len);
+ p_cb->p_path[p_bta_fs_cfg->max_file_len] = '\0';
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open (p_cb->p_path,
+ (BTA_FS_O_CREAT | BTA_FS_O_TRUNC | BTA_FS_O_RDWR),
+ p_cb->file_length, BTA_FTS_CI_OPEN_EVT,
+ p_cb->app_id);
+ }
+ else /* Access denied */
+ {
+ bta_fts_clean_getput(p_cb, TRUE);
+ OBX_PutRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL);
+ }
+ break;
+
+ case BTA_FT_OPER_GET:
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open (p_cb->p_path, BTA_FS_O_RDONLY, 0,
+ BTA_FTS_CI_OPEN_EVT, p_cb->app_id);
+ }
+ else /* Denied */
+ bta_fts_get_file_rsp(OBX_RSP_UNAUTHORIZED, 0);
+ break;
+
+ case BTA_FT_OPER_DEL_FILE: /* Request is a DELETE file */
+ p_rsp = OBX_PutRsp;
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ objevt.p_name = p_cb->p_path;
+ objevt.status = BTA_FTS_OK;
+ if ((status = bta_fs_co_unlink(p_cb->p_path, p_cb->app_id)) != BTA_FS_CO_OK)
+ {
+ objevt.status = BTA_FTS_FAIL;
+ }
+
+ /* Notify application of delete attempt */
+ p_cb->p_cback(BTA_FTS_DEL_CMPL_EVT, (tBTA_FTS *)&objevt);
+ }
+ break;
+
+ case BTA_FT_OPER_DEL_DIR: /* Request is a DELETE folder */
+ p_rsp = OBX_PutRsp;
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ objevt.p_name = p_cb->p_path;
+ objevt.status = BTA_FTS_OK;
+ if ((status = bta_fs_co_rmdir(p_cb->p_path, p_cb->app_id)) != BTA_FS_CO_OK)
+ {
+ objevt.status = BTA_FTS_FAIL;
+ }
+
+ /* Notify application of delete attempt */
+ p_cb->p_cback(BTA_FTS_DEL_CMPL_EVT, (tBTA_FTS *)&objevt);
+ }
+ break;
+
+ case BTA_FT_OPER_CHG_DIR: /* Request is a Change Folder */
+ p_rsp = OBX_SetPathRsp;
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ status = BTA_FS_CO_OK;
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+ APPL_TRACE_DEBUG1("FTS: SET NEW PATH [%s]", p_cb->p_workdir);
+ bta_fs_co_setdir(p_cb->p_workdir, p_cb->app_id);
+ }
+ break;
+
+ case BTA_FT_OPER_MK_DIR: /* Request is a Make Folder */
+ p_rsp = OBX_SetPathRsp;
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ if ((status = bta_fs_co_mkdir(p_cb->p_path, p_cb->app_id)) == BTA_FS_CO_OK)
+ {
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+ APPL_TRACE_DEBUG1("FTS: SET NEW PATH [%s]", p_cb->p_workdir);
+ bta_fs_co_setdir(p_cb->p_workdir, p_cb->app_id);
+ }
+ }
+ break;
+
+ case BTA_FT_OPER_COPY_ACT:
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ p_cb->cout_active = TRUE;
+ bta_fs_co_copy(p_cb->p_path, p_cb->p_dest, p_cb->perms, BTA_FTS_CI_OPEN_EVT, p_cb->app_id);
+ }
+ else
+ p_rsp = OBX_ActionRsp;
+ break;
+
+ case BTA_FT_OPER_MOVE_ACT:
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ p_cb->cout_active = TRUE;
+ bta_fs_co_rename(p_cb->p_path, p_cb->p_dest, p_cb->perms, BTA_FTS_CI_OPEN_EVT, p_cb->app_id);
+ }
+ else
+ p_rsp = OBX_ActionRsp;
+ break;
+
+ case BTA_FT_OPER_SET_PERM:
+ if (access == BTA_FT_ACCESS_ALLOW)
+ {
+ p_cb->cout_active = TRUE;
+ bta_fs_co_set_perms(p_cb->p_path, p_cb->perms, BTA_FTS_CI_OPEN_EVT, p_cb->app_id);
+ }
+ else
+ p_rsp = OBX_ActionRsp;
+ break;
+
+ default:
+ p_cb->acc_active = old_acc_active;
+ APPL_TRACE_WARNING1("FTS ACCRSP: Unknown tBTA_FT_OPER value (%d)",
+ p_cb->acc_active);
+ }
+ if(p_rsp)
+ {
+ switch (status)
+ {
+ case BTA_FS_CO_OK:
+ rsp_code = OBX_RSP_OK;
+ break;
+ case BTA_FS_CO_ENOTEMPTY:
+ rsp_code = OBX_RSP_PRECONDTN_FAILED;
+ break;
+ case BTA_FS_CO_EACCES:
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ break;
+ default:
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+ utl_freebuf((void**)&p_cb->p_dest);
+
+ p_cb->obx_oper = FTS_OP_NONE;
+ (*p_rsp)(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_api_close
+**
+** Description Handle an api close event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_api_close(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ BD_ADDR bd_addr;
+ if (OBX_GetPeerAddr(p_cb->obx_handle, bd_addr) != 0)
+ {
+ /* resources will be freed at BTA_PBS_OBX_CLOSE_EVT */
+ OBX_DisconnectRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, NULL);
+ }
+ else
+ {
+ p_cb->p_cback(BTA_FTS_CLOSE_EVT, 0);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_ci_write
+**
+** Description Continue with the current write operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_ci_write(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->disabling)
+ {
+ bta_fts_sm_execute(p_cb,BTA_FTS_DISABLE_CMPL_EVT, p_data);
+ }
+
+ /* Process write call-in event if operation is still active */
+ if (p_cb->obx_oper == FTS_OP_PUT_FILE)
+ {
+ if (p_data->write_evt.status == BTA_FS_CO_OK)
+ rsp_code = OBX_RSP_OK;
+ else
+ {
+ if (p_data->write_evt.status == BTA_FS_CO_ENOSPACE)
+ rsp_code = OBX_RSP_DATABASE_FULL;
+ bta_fts_clean_getput(p_cb, TRUE);
+ }
+
+ /* Process response to OBX client */
+ bta_fts_put_file_rsp(rsp_code);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_ci_read
+**
+** Description Handles the response to a read call-out request.
+** This is called within the OBX get file request. If the
+** operation has completed, the OBX response is sent out;
+** otherwise a read for additional data is made.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_ci_read(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FS_CI_READ_EVT *p_revt = &p_data->read_evt;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->disabling)
+ {
+ bta_fts_sm_execute(p_cb,BTA_FTS_DISABLE_CMPL_EVT, p_data);
+ }
+
+ /* Process read call-in event if operation is still active */
+ if (p_cb->obx_oper == FTS_OP_GET_FILE && p_revt->fd == p_cb->fd)
+ {
+ /* Read was successful, not finished yet */
+ if (p_revt->status == BTA_FS_CO_OK)
+ rsp_code = OBX_RSP_CONTINUE;
+
+ /* Read was successful, end of file has been detected */
+ else if (p_revt->status == BTA_FS_CO_EOF)
+ rsp_code = OBX_RSP_OK;
+
+ /* Process response to OBX client */
+ bta_fts_get_file_rsp(rsp_code, p_revt->num_read);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_ci_resume
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_ci_resume(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_UTL_COD cod;
+
+ p_cb->state = BTA_FTS_LISTEN_ST;
+ APPL_TRACE_EVENT1("bta_fts_ci_resume status:%d", p_data->resume_evt.status);
+ /* Set the File Transfer service class bit */
+ cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
+ utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+ if (p_data->resume_evt.status == BTA_FS_CO_OK)
+ {
+ OBX_AddSuspendedSession (p_cb->obx_handle, p_data->resume_evt.p_addr,
+ p_data->resume_evt.p_sess_info, p_data->resume_evt.timeout,
+ p_data->resume_evt.ssn, p_data->resume_evt.offset);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_ci_open
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_ci_open(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FS_CI_OPEN_EVT *p_open = &p_data->open_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 num_hdrs;
+ BOOLEAN endpkt;
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->disabling)
+ {
+ bta_fts_sm_execute(p_cb,BTA_FTS_DISABLE_CMPL_EVT, p_data);
+ }
+
+ /* If using OBEX 1.5 */
+ if ( p_cb->obx_oper & FTS_OP_RESUME)
+ {
+ /* clear the FTS_OP_RESUME when the first request is received.
+ * We may need to adjust ssn/offset */
+ if ((p_open->fd >= 0) && (p_cb->obx_oper == FTS_OP_RESUME))
+ {
+ /* file is open successfully when the resumed obex op is FTS_OP_NONE
+ * close this file */
+ bta_fs_co_close(p_open->fd, p_cb->app_id);
+ p_open->fd = BTA_FS_INVALID_FD;
+ }
+ p_cb->fd = p_open->fd;
+ return;
+ }
+
+ /* Only process file get or put operations */
+ if (p_cb->obx_oper == FTS_OP_GET_FILE)
+ {
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->file_length = p_open->file_size;
+ p_cb->fd = p_open->fd;
+
+ /* Add the length header if available */
+ if (p_cb->file_length != BTA_FS_LEN_UNKNOWN)
+ {
+ OBX_AddLengthHdr(p_obx->p_pkt, p_cb->file_length);
+ if (p_cb->file_length > 0)
+ rsp_code = OBX_RSP_CONTINUE;
+ else
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE);
+ }
+
+ /* Send continuation response with the length of the file and no body */
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+
+ if (p_cb->file_length == 0)
+ bta_fts_clean_getput(p_cb, FALSE);
+ }
+ else
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else /* File could not be found */
+ rsp_code = OBX_RSP_NOT_FOUND;
+
+ /* Send OBX response if an error occurred */
+ bta_fts_get_file_rsp(rsp_code, 0);
+ }
+ }
+ else if (p_cb->obx_oper == FTS_OP_PUT_FILE)
+ {
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->fd = p_open->fd;
+
+ /* Read in start of body if there is a body header */
+ num_hdrs = OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start,
+ &p_obx->bytes_left, &endpkt);
+ if (num_hdrs == 1)
+ {
+ rsp_code = OBX_RSP_PART_CONTENT; /* Do not send OBX response yet */
+ /* Initiate the writing out of the data */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_FTS_CI_WRITE_EVT, 0,
+ p_cb->app_id);
+ }
+ else if (num_hdrs > 1) /* Cannot handle multiple body headers */
+ {
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ bta_fts_clean_getput(p_cb, TRUE);
+ }
+ else /* No body: respond with an OK so client can start sending the data */
+ p_obx->bytes_left = 0;
+
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ {
+ bta_fts_put_file_rsp(rsp_code);
+ }
+ }
+ else
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else if (p_open->status == BTA_FS_CO_ENOSPACE)
+ rsp_code = OBX_RSP_DATABASE_FULL;
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ /* Send OBX response now if an error occurred */
+ bta_fts_put_file_rsp(rsp_code);
+ }
+ }
+ /* If using OBEX 1.5 */
+ else
+ {
+ /* must be action commands BTA_FT_OPER_COPY_ACT - BTA_FT_OPER_SET_PERM*/
+ switch (p_open->status)
+ {
+ case BTA_FS_CO_OK:
+ rsp_code = OBX_RSP_OK;
+ break;
+ case BTA_FS_CO_EACCES:
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ break;
+ case BTA_FS_CO_EIS_DIR:
+ rsp_code = OBX_RSP_FORBIDDEN;
+ default:
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+ utl_freebuf((void**)&p_cb->p_dest);
+ p_cb->obx_oper = FTS_OP_NONE;
+ OBX_ActionRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_ci_direntry
+**
+** Description Continue getting the current directory entry operation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_ci_direntry(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ UINT8 rsp_code;
+ BOOLEAN free_pkt = TRUE;
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->disabling)
+ {
+ bta_fts_sm_execute(p_cb,BTA_FTS_DISABLE_CMPL_EVT, p_data);
+ }
+
+ /* Process dirent listing call-in event if operation is still active */
+ if (p_cb->obx_oper == FTS_OP_LISTING)
+ {
+ switch (p_data->getdir_evt.status)
+ {
+ case BTA_FS_CO_OK: /* Valid new entry */
+ free_pkt = FALSE;
+ if ((rsp_code = bta_fts_add_list_entry()) != OBX_RSP_PART_CONTENT)
+ bta_fts_end_of_list(rsp_code);
+ break;
+
+ case BTA_FS_CO_EODIR: /* End of list (entry not valid) */
+ free_pkt = FALSE;
+ bta_fts_end_of_list(OBX_RSP_OK);
+ break;
+
+ case BTA_FS_CO_FAIL: /* Error occurred */
+ bta_fts_end_of_list(OBX_RSP_NOT_FOUND);
+ break;
+ }
+ }
+
+ if (free_pkt)
+ utl_freebuf((void **)&p_cb->obx.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_obx_connect
+**
+** Description Process the OBX connect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_connect(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ tOBX_SESS_EVT *p_sess = &p_data->obx_evt.param.sess;
+
+ APPL_TRACE_DEBUG1("bta_fts_obx_connect obx_event=%d", p_evt->obx_event);
+ if (p_evt->obx_event == OBX_SESSION_REQ_EVT)
+ {
+ APPL_TRACE_EVENT3("sess_op:%d obj_offset:x%x ssn:%d", p_sess->sess_op, p_sess->obj_offset, p_sess->ssn);
+
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+
+ bta_fs_co_session_info(p_cb->bd_addr, p_sess->p_sess_info, p_sess->ssn,
+ BTA_FS_CO_SESS_ST_ACTIVE, p_cb->p_workdir, &p_cb->obx_oper, p_cb->app_id);
+ APPL_TRACE_DEBUG1("obx_oper:%d", p_cb->obx_oper);
+ if (p_sess->sess_op == OBX_SESS_OP_CREATE)
+ {
+ p_cb->state = BTA_FTS_LISTEN_ST;
+ p_cb->obx_oper = FTS_OP_NONE;
+ }
+ else if (p_sess->sess_op == OBX_SESS_OP_RESUME)
+ {
+ p_cb->state = BTA_FTS_LISTEN_ST;
+ p_cb->resume_ssn = p_sess->ssn;
+ APPL_TRACE_EVENT1("resume ssn:%d", p_sess->ssn);
+ if (p_cb->obx_oper)
+ {
+ bta_fs_co_resume_op(p_sess->obj_offset, BTA_FTS_CI_OPEN_EVT, p_cb->app_id);
+ p_cb->obx_oper |= FTS_OP_RESUME;
+ }
+ }
+ return;
+ }
+
+ p_cb->peer_mtu = p_evt->param.conn.mtu;
+ memcpy(p_cb->bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN);
+ APPL_TRACE_EVENT2("FTS Connect: peer mtu 0x%04x handle:0x%x", p_cb->peer_mtu, p_evt->handle);
+
+ if (!p_evt->param.conn.no_rsp)
+ {
+ OBX_ConnectRsp(p_evt->handle, OBX_RSP_OK, (BT_HDR *)NULL);
+
+ /* Reset to the root directory */
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+
+ bta_fs_co_setdir(p_cb->p_workdir, p_cb->app_id);
+ }
+
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_FTS, p_cb->app_id, p_cb->bd_addr);
+
+ /* Notify the MMI that a connection has been opened */
+ p_cb->p_cback(BTA_FTS_OPEN_EVT, (tBTA_FTS*)p_cb->bd_addr);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_obx_disc
+**
+** Description Process the OBX disconnect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_disc(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code;
+
+ rsp_code = (p_evt->obx_event == OBX_DISCONNECT_REQ_EVT) ? OBX_RSP_OK
+ : OBX_RSP_BAD_REQUEST;
+ OBX_DisconnectRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_obx_close
+**
+** Description Process the OBX link lost event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_close(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->cout_active)
+ bta_fts_sm_execute(p_cb, BTA_FTS_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_obx_abort
+**
+** Description Process the OBX abort event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_abort(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ switch (p_cb->obx_oper)
+ {
+ case FTS_OP_LISTING:
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+ bta_fts_clean_list(p_cb);
+ break;
+
+ case FTS_OP_GET_FILE:
+ case FTS_OP_PUT_FILE:
+ bta_fts_clean_getput(p_cb, TRUE);
+ break;
+
+ default: /* Reply OK to the client */
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+
+ OBX_AbortRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_obx_password
+**
+** Description Process the OBX password request
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_password(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ tBTA_FTS_AUTH *p_auth;
+ BOOLEAN is_challenged;
+ tOBX_AUTH_OPT options;
+
+ if ((p_auth = (tBTA_FTS_AUTH *)GKI_getbuf(sizeof(tBTA_FTS_AUTH))) != NULL)
+ {
+ memset(p_auth, 0, sizeof(tBTA_FTS_AUTH));
+
+ /* Extract user id from packet (if available) */
+ if (OBX_ReadAuthParams(p_data->obx_evt.p_pkt, &p_auth->p_userid,
+ &p_auth->userid_len,
+ &is_challenged, &options))
+ {
+ if (options & OBX_AO_USR_ID)
+ p_auth->userid_required = TRUE;
+ }
+
+ /* Don't need OBX packet any longer */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ /* Notify application */
+ p_cb->p_cback(BTA_FTS_AUTH_EVT, (tBTA_FTS *)p_auth);
+
+ GKI_freebuf(p_auth);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_obx_put
+**
+** Description Process the OBX file put and delete file/folder events
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_put(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+ BOOLEAN rsp_now = TRUE;
+ BOOLEAN free_in_pkt = TRUE;
+ UINT8 obx_oper = bta_fts_cb.obx_oper;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 num_hdrs;
+ BOOLEAN endpkt;
+
+ APPL_TRACE_EVENT1("bta_fts_obx_put oper=x%x", p_cb->obx_oper);
+
+ /* If using OBEX 1.5 */
+ if ( p_cb->obx_oper & FTS_OP_RESUME)
+ {
+ APPL_TRACE_EVENT2("bta_fts_obx_put ssn:%d resume ssn:%d", p_evt->param.get.ssn, p_cb->resume_ssn);
+ p_cb->obx_oper &= ~FTS_OP_RESUME;
+ num_hdrs = OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start,
+ &p_obx->bytes_left, &endpkt);
+ if ((p_evt->param.get.ssn != p_cb->resume_ssn) && (p_cb->fd >= 0))
+ {
+ if ((p_cb->obx_oper == FTS_OP_PUT_FILE) && (num_hdrs == 0) && ((p_evt->param.get.ssn + 1) == p_cb->resume_ssn))
+ {
+ APPL_TRACE_EVENT0("client did not get the last PUT response. Just want another response pkt");
+ }
+ else
+ bta_fs_co_sess_ssn(p_cb->fd, p_evt->param.put.ssn, p_cb->app_id);
+ }
+ }
+
+ /* If currently processing a PUT, use the current name */
+ if (bta_fts_cb.obx_oper == FTS_OP_PUT_FILE)
+ {
+ free_in_pkt = FALSE; /* Hang on to Obx packet until done */
+ bta_fts_proc_put_file(p_evt->p_pkt, p_cb->p_name, p_evt->param.put.final, obx_oper);
+ rsp_now = FALSE; /* Response sent after processing the request */
+ }
+ else /* This is a new request */
+ {
+ /* Pull out the name header if it exists */
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1))) != NULL)
+ {
+ if (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *) p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+ /* Is Put operation Delete, Create, or Put */
+ if (p_evt->param.put.type == OBX_PT_DELETE)
+ {
+ APPL_TRACE_EVENT1("FTS File/Folder Delete: Name [%s]", p_cb->p_name);
+ bta_fts_delete(p_evt, p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_name);
+ }
+ else /* File Put or File Create */
+ {
+ free_in_pkt = FALSE; /* Hang on to Obx packet until done */
+ APPL_TRACE_EVENT1("FTS File Put: Name [%s]", p_cb->p_name);
+ bta_fts_proc_put_file(p_evt->p_pkt, p_cb->p_name, p_evt->param.put.final, obx_oper);
+ }
+
+ rsp_now = FALSE; /* Response sent after processing the request */
+ }
+ else /* Must have a name header */
+ {
+ utl_freebuf((void**)&p_cb->p_name);
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+
+ /* Respond right away if an error has been detected processing request */
+ if (rsp_now)
+ OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+
+ /* Done with Obex packet */
+ if (free_in_pkt)
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_obx_get
+**
+** Description Process the OBX file get and folder listing events
+** If the type header is not folder listing, then pulling a file.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_get(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT16 len;
+ BOOLEAN is_file_get = TRUE; /* Set to false if folder listing */
+ UINT8 *p_type;
+
+ APPL_TRACE_EVENT1("bta_fts_obx_get:%d", bta_fts_cb.obx_oper);
+
+ /* If using OBEX 1.5 */
+ if ( p_cb->obx_oper & FTS_OP_RESUME)
+ {
+ p_cb->obx_oper &= ~FTS_OP_RESUME;
+ APPL_TRACE_DEBUG3("ssn:%d resume ssn:%d, op:%d", p_evt->param.get.ssn, p_cb->resume_ssn, bta_fts_cb.obx_oper );
+ if (bta_fts_cb.obx_oper == FTS_OP_LISTING)
+ {
+ /* abort the listing */
+ bta_fts_end_of_list(OBX_RSP_INTRNL_SRVR_ERR);
+ return;
+ }
+ else if ((p_evt->param.get.ssn != p_cb->resume_ssn) && (p_cb->fd >= 0))
+ {
+ APPL_TRACE_EVENT2("ssn:%d resume ssn:%d", p_evt->param.get.ssn, p_cb->resume_ssn);
+ bta_fs_co_sess_ssn(p_cb->fd, p_evt->param.get.ssn, p_cb->app_id);
+ }
+ }
+
+ /* If currently processing a GET, use the current name */
+ if (bta_fts_cb.obx_oper == FTS_OP_LISTING)
+ bta_fts_getdirlist(p_cb->p_name);
+ else if (bta_fts_cb.obx_oper == FTS_OP_GET_FILE)
+ bta_fts_proc_get_file(p_cb->p_name);
+
+ else /* This is a new request */
+ {
+ /* Pull out the name header if it exists */
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1))) != NULL)
+ {
+ if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+ GKI_freebuf(p_cb->p_name);
+ p_cb->p_name = NULL;
+ }
+ }
+
+ /* See if getting a folder listing */
+ if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len))
+ {
+ if (!memcmp(p_type, BTA_FTS_FOLDER_LISTING_TYPE, len))
+ {
+ is_file_get = FALSE;
+ bta_fts_getdirlist(p_cb->p_name);
+ }
+ }
+
+ /* Initiate the Get File request if not folder listing */
+ if (is_file_get)
+ {
+ if (p_cb->p_name)
+ {
+ APPL_TRACE_EVENT1("FTS File Get: Name [%s]", p_cb->p_name);
+ }
+ bta_fts_proc_get_file(p_cb->p_name);
+ }
+ }
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_obx_setpath
+**
+** Description Process the FTP change or make directory requests
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_setpath(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_BAD_REQUEST;
+ tOBX_SETPATH_FLAG *p_flag = &p_evt->param.sp.flag;
+ tBTA_FT_OPER ft_op = 0;
+
+ /* Verify flags and handle before accepting */
+ if (p_evt->handle == p_cb->obx_handle &&
+ (((*p_flag) & FLAGS_ARE_MASK) != FLAGS_ARE_ILLEGAL))
+ {
+ p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1));
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len +
+ p_bta_fs_cfg->max_file_len + 2));
+ if (p_cb->p_name != NULL && p_cb->p_path != NULL)
+ {
+ if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+ utl_freebuf((void **)&p_cb->p_name); /* no name header */
+ }
+ else if (!p_cb->p_name)
+ {
+ /* empty name header set to null terminated string */
+ p_cb->p_name[0] = '\0';
+ }
+
+
+ /* Determine if operation is mkdir */
+ if (!((*p_flag) & OBX_SPF_NO_CREATE))
+ {
+ rsp_code = bta_fts_mkdir(p_evt->p_pkt, &ft_op);
+
+ /* If the directory already exists, silently perform change directory */
+ if(rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* Note BACKUP flag must be FALSE for mkdir operation */
+ rsp_code = bta_fts_chdir(p_evt->p_pkt, FALSE, &ft_op);
+ }
+ }
+ else /* Operation is chdir */
+ rsp_code = bta_fts_chdir(p_evt->p_pkt, (BOOLEAN)((*p_flag) & OBX_SPF_BACKUP), &ft_op);
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+
+ if (ft_op)
+ {
+ bta_fts_req_app_access(ft_op, p_cb);
+ }
+ else
+ {
+ OBX_SetPathRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+ }
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/* Using OBEX 1.5 */
+/*******************************************************************************
+**
+** Function bta_fts_obx_action
+**
+** Description Process the FTP action requests
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_action(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_BAD_REQUEST;
+ tBTA_FT_OPER ft_op = 0;
+ UINT8 action;
+ BOOLEAN is_dir;
+ BOOLEAN has_perms = FALSE;
+ char *p_dest_name = NULL;
+ char *p_newpath = NULL;
+
+ /* Verify flags and handle before accepting */
+ if (p_evt->handle == p_cb->obx_handle )
+ {
+ if (OBX_ReadActionIdHdr(p_evt->p_pkt, &action))
+ {
+ p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1));
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len +
+ p_bta_fs_cfg->max_file_len + 2));
+ p_newpath = p_cb->p_path;
+ if ((p_cb->p_name != NULL) && (p_cb->p_path != NULL) &&
+ ((strlen(p_cb->p_name) + strlen(p_cb->p_workdir) + 1) <= p_bta_fs_cfg->max_path_len))
+
+ {
+ if (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len) &&
+ p_cb->p_name[0])
+ {
+ /* the packet has non-empty name header */
+ sprintf(p_newpath, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_cb->p_name);
+ if (((bta_fs_co_access(p_newpath, BTA_FS_ACC_EXIST,
+ &is_dir, p_cb->app_id)) == BTA_FS_CO_OK))
+ {
+ /* the src object exists */
+ ft_op = BTA_FT_OPER_COPY_ACT + action;
+ }
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+
+ if (ft_op)
+ {
+ memset (p_cb->perms, 0, BTA_FS_PERM_SIZE);
+ /* it's SetPermission -> need Permission Header */
+ if (OBX_ReadPermissionHdr(p_evt->p_pkt, &p_cb->perms[BTA_FS_PERM_USER],
+ &p_cb->perms[BTA_FS_PERM_GROUP], &p_cb->perms[BTA_FS_PERM_OTHER]))
+ {
+ has_perms = TRUE;
+ }
+ if (action != BTA_FT_ACT_PERMISSION)
+ {
+ /* it's Move or Copy -> need DestName Header */
+ p_dest_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1));
+ p_cb->p_dest = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len +
+ p_bta_fs_cfg->max_file_len + 2));
+ p_newpath = p_cb->p_dest;
+ if (p_dest_name && p_cb->p_dest)
+ {
+ if (OBX_ReadUtf8DestNameHdr(p_evt->p_pkt, (UINT8 *)p_dest_name, p_bta_fs_cfg->max_file_len) &&
+ p_dest_name[0])
+ {
+ if (p_dest_name[0] == '/' || p_dest_name[0] == '\\')
+ {
+ /* the packet has non-empty DestName header */
+ sprintf(p_newpath, "%s%c%s", p_cb->p_rootpath,
+ p_bta_fs_cfg->path_separator, p_dest_name);
+ }
+ else
+ {
+ /* the packet has non-empty DestName header */
+ sprintf(p_newpath, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_dest_name);
+ }
+ if (((bta_fs_co_access(p_newpath, BTA_FS_ACC_EXIST,
+ &is_dir, p_cb->app_id)) == BTA_FS_CO_FAIL))
+ {
+ /* the dest object does not exist */
+ rsp_code = OBX_RSP_OK;
+ }
+ }
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ else if (has_perms)
+ {
+ /* the SetPermission action must have the permission header */
+ rsp_code = OBX_RSP_OK;
+ }
+ }
+
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+
+ if(rsp_code == OBX_RSP_OK)
+ {
+ bta_fts_req_app_access(ft_op, p_cb);
+ }
+ else
+ {
+ OBX_ActionRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+ utl_freebuf((void**)&p_dest_name);
+ utl_freebuf((void**)&p_cb->p_dest);
+ }
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+/* end of using OBEX 1.5 */
+
+/*******************************************************************************
+**
+** Function bta_fts_appl_tout
+**
+** Description Process the FTS application timeout event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_appl_tout(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_conn_err_rsp
+**
+** Description Process the OBX error response
+** Connect request received in wrong state, or bad request
+** from client
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_conn_err_rsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ OBX_ConnectRsp(p_data->obx_evt.handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+}
+
+/* Using OBEX 1.5 */
+/*******************************************************************************
+**
+** Function bta_fts_session_req
+**
+** Description Process the OBX session req in connected state
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_session_req(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ tOBX_SESS_EVT *p_sess = &p_data->obx_evt.param.sess;
+ UINT8 rsp_code = OBX_RSP_OK;
+ UINT32 offset = 0;
+
+ if (p_evt->obx_event == OBX_SESSION_REQ_EVT)
+ {
+ APPL_TRACE_EVENT2("sess_op:%d ssn:%d", p_sess->sess_op, p_sess->ssn);
+ switch (p_sess->sess_op)
+ {
+ case OBX_SESS_OP_SUSPEND:
+ bta_fs_co_suspend(p_cb->bd_addr, p_sess->p_sess_info, p_sess->ssn, &p_sess->timeout, &offset, p_cb->obx_oper, p_cb->app_id);
+ p_cb->state = BTA_FTS_CLOSING_ST;
+ p_cb->suspending = TRUE;
+ break;
+
+ case OBX_SESS_OP_CLOSE:
+ bta_fs_co_session_info(p_cb->bd_addr, p_sess->p_sess_info, 0, BTA_FS_CO_SESS_ST_NONE, NULL, NULL, p_cb->app_id);
+ p_cb->state = BTA_FTS_CLOSING_ST;
+ break;
+
+ case OBX_SESS_OP_CREATE:
+ case OBX_SESS_OP_RESUME:
+ p_cb->state = BTA_FTS_CONN_ST;
+ rsp_code = OBX_RSP_FORBIDDEN;
+ break;
+ }
+ OBX_SessionRsp (p_evt->handle, rsp_code, p_sess->ssn, offset, NULL);
+ return;
+ }
+ else if (p_evt->obx_event == OBX_SESSION_INFO_EVT)
+ {
+ if ((p_cb->obx_oper != FTS_OP_GET_FILE) && (p_cb->obx_oper != FTS_OP_PUT_FILE) && (p_cb->obx_oper != FTS_OP_LISTING))
+ {
+ /* the other obx ops are single transaction.
+ * If the link is dropped before the transaction ends, let the client re-transmit the request */
+ p_sess->ssn--;
+ p_cb->obx_oper = FTS_OP_NONE;
+ }
+ bta_fs_co_suspend(p_cb->bd_addr, p_sess->p_sess_info, p_sess->ssn,
+ &p_sess->timeout, &offset, p_cb->obx_oper, p_cb->app_id);
+ OBX_AddSuspendedSession (p_cb->obx_handle, p_cb->bd_addr,
+ p_sess->p_sess_info, p_sess->timeout,
+ p_sess->ssn, offset);
+ p_cb->suspending = TRUE;
+ }
+ else
+ {
+ p_cb->state = BTA_FTS_CONN_ST;
+ bta_fts_conn_err_rsp (p_cb, p_data);
+ }
+}
+/* End of using OBEX 1.5 */
+
+/*******************************************************************************
+**
+** Function bta_fts_disc_err_rsp
+**
+** Description Process the OBX error response
+** Disconnect request received in wrong state, or bad request
+** from client
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_disc_err_rsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ OBX_DisconnectRsp(p_data->obx_evt.handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_gasp_err_rsp
+**
+** Description Process the OBX error response for Get, Abort, Setpath, and Put.
+**
+** The rsp_code field of tBTA_FTS_DATA (obx_evt) contains the
+** response code to be sent to OBEX, and the obx_event field
+** contains the current OBEX event.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_gasp_err_rsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ tBTA_FTS_OBX_RSP *p_rsp = NULL;
+
+ switch (p_evt->obx_event)
+ {
+ case OBX_PUT_REQ_EVT:
+ p_rsp = OBX_PutRsp;
+ break;
+ case OBX_GET_REQ_EVT:
+ p_rsp = OBX_GetRsp;
+ break;
+ case OBX_SETPATH_REQ_EVT:
+ p_rsp = OBX_SetPathRsp;
+ break;
+ case OBX_ABORT_REQ_EVT:
+ p_rsp = OBX_AbortRsp;
+ break;
+ case OBX_ACTION_REQ_EVT:
+ p_rsp = OBX_ActionRsp;
+ break;
+ }
+ if(p_rsp)
+ (*p_rsp)(p_evt->handle, p_evt->rsp_code, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_close_complete
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_close_complete(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ p_cb->cout_active = FALSE;
+ bta_fts_clean_getput(p_cb, TRUE);
+ bta_fts_clean_list(p_cb);
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_FTS ,p_cb->app_id, p_cb->bd_addr);
+
+
+
+
+ /* Notify the MMI that a connection has been closed */
+ p_cb->p_cback(BTA_FTS_CLOSE_EVT, (tBTA_FTS*)p_cb->bd_addr);
+ memset(p_cb->bd_addr, 0, BD_ADDR_LEN);
+
+ if (p_data->obx_evt.p_pkt)
+ APPL_TRACE_WARNING0("FTS: OBX CLOSE CALLED WITH non-NULL Packet!!!");
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_disable_cmpl
+**
+** Description Finishes the memory cleanup before shutting down server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_disable_cmpl(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ bta_fts_disable_cleanup(p_cb);
+}
+
+/*****************************************************************************
+** Callback Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_fts_obx_cback
+**
+** Description OBX callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_FTS_OBX_EVENT *p_obx_msg;
+ UINT16 event = 0;
+ UINT16 size = sizeof(tBTA_FTS_OBX_EVENT);
+
+#if BTA_FTS_DEBUG == TRUE
+ APPL_TRACE_DEBUG2("OBX Event Callback: obx_event [%s] %d", fts_obx_evt_code(obx_event), obx_event);
+#endif
+
+ switch(obx_event)
+ {
+ case OBX_SESSION_INFO_EVT: /* the session information event to resume the session. */
+ size += OBX_SESSION_INFO_SIZE;
+ /* Falls through */
+
+ case OBX_SESSION_REQ_EVT:
+ case OBX_CONNECT_REQ_EVT:
+ event = BTA_FTS_OBX_CONN_EVT;
+ break;
+ case OBX_ACTION_REQ_EVT:
+ event = BTA_FTS_OBX_ACTION_EVT;
+ break;
+ case OBX_DISCONNECT_REQ_EVT:
+ event = BTA_FTS_OBX_DISC_EVT;
+ break;
+ case OBX_PUT_REQ_EVT:
+ event = BTA_FTS_OBX_PUT_EVT;
+ break;
+ case OBX_GET_REQ_EVT:
+ event = BTA_FTS_OBX_GET_EVT;
+ break;
+ case OBX_SETPATH_REQ_EVT:
+ event = BTA_FTS_OBX_SETPATH_EVT;
+ break;
+ case OBX_ABORT_REQ_EVT:
+ event = BTA_FTS_OBX_ABORT_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_FTS_OBX_CLOSE_EVT;
+ break;
+ case OBX_TIMEOUT_EVT:
+ break;
+ case OBX_PASSWORD_EVT:
+ event = BTA_FTS_OBX_PASSWORD_EVT;
+ break;
+ default:
+ /* Unrecognized packet; disconnect the session */
+ if (p_pkt)
+ event = BTA_FTS_OBX_DISC_EVT;
+ }
+
+ /* send event to BTA, if any */
+ if (event && (p_obx_msg =
+ (tBTA_FTS_OBX_EVENT *) GKI_getbuf(size)) != NULL)
+ {
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+
+ if (obx_event == OBX_SESSION_INFO_EVT)
+ {
+ p_obx_msg->param.sess.p_sess_info = (UINT8 *)(p_obx_msg + 1);
+ memcpy (p_obx_msg->param.sess.p_sess_info, param.sess.p_sess_info, OBX_SESSION_INFO_SIZE);
+ }
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+
+/*****************************************************************************
+** Local FTP Event Processing Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_fts_req_app_access
+**
+** Description Sends an access request event to the application.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_req_app_access (tBTA_FT_OPER oper, tBTA_FTS_CB *p_cb)
+{
+ tBTA_FTS_ACCESS *p_acc_evt;
+ char *p_devname;
+
+ /* Notify the application that a put or get file has been requested */
+ if ((p_acc_evt = (tBTA_FTS_ACCESS *)GKI_getbuf(sizeof(tBTA_FTS_ACCESS))) != NULL)
+ {
+ memset(p_acc_evt, 0, sizeof(tBTA_FTS_ACCESS));
+
+ APPL_TRACE_API1("ACCESS REQ: [%s]", p_cb->p_path);
+
+ p_acc_evt->p_name = p_cb->p_path;
+ p_acc_evt->p_dest_name = p_cb->p_dest;
+ memcpy(p_acc_evt->perms, p_cb->perms, BTA_FS_PERM_SIZE);
+
+ p_acc_evt->size = p_cb->file_length;
+ p_acc_evt->oper = p_cb->acc_active = oper;
+ bdcpy(p_acc_evt->bd_addr, p_cb->bd_addr);
+ if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL)
+ BCM_STRNCPY_S((char *)p_acc_evt->dev_name, sizeof(p_acc_evt->dev_name), p_devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ p_cb->p_cback(BTA_FTS_ACCESS_EVT, (tBTA_FTS *)p_acc_evt);
+ GKI_freebuf(p_acc_evt);
+ }
+}
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_FTS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function fts_obx_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *fts_obx_evt_code(tOBX_EVENT evt_code)
+{
+ switch(evt_code)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ return "OBX_CONNECT_REQ_EVT";
+ case OBX_DISCONNECT_REQ_EVT:
+ return "OBX_DISCONNECT_REQ_EVT";
+ case OBX_PUT_REQ_EVT:
+ return "OBX_PUT_REQ_EVT";
+ case OBX_GET_REQ_EVT:
+ return "OBX_GET_REQ_EVT";
+ case OBX_SETPATH_REQ_EVT:
+ return "OBX_SETPATH_REQ_EVT";
+ case OBX_ABORT_REQ_EVT:
+ return "OBX_ABORT_REQ_EVT";
+ case OBX_CLOSE_IND_EVT:
+ return "OBX_CLOSE_IND_EVT";
+ case OBX_TIMEOUT_EVT:
+ return "OBX_TIMEOUT_EVT";
+ case OBX_PASSWORD_EVT:
+ return "OBX_PASSWORD_EVT";
+ case OBX_SESSION_REQ_EVT:
+ return "OBX_SESSION_REQ_EVT";
+ case OBX_ACTION_REQ_EVT:
+ return "OBX_ACTION_REQ_EVT";
+ case OBX_SESSION_INFO_EVT:
+ return "OBX_SESSION_INFO_EVT";
+
+ default:
+ return "unknown OBX event code";
+ }
+}
+#endif /* Debug Functions */
+#endif /* BTA_FT_INCLUDED */
diff --git a/bta/ft/bta_fts_api.c b/bta/ft/bta_fts_api.c
new file mode 100644
index 0000000..be359e0
--- /dev/null
+++ b/bta/ft/bta_fts_api.c
@@ -0,0 +1,230 @@
+/*****************************************************************************
+**
+** Name: bta_fts_api.c
+**
+** Description: This is the implementation of the API for the file
+** transfer server subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_FT_INCLUDED) && (BTA_FT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_fs_api.h"
+#include "bta_fts_int.h"
+
+// btla-specific ++
+//todo sdh
+
+/* Maximum path length supported by MMI */
+#ifndef BTA_FS_PATH_LEN
+#define BTA_FS_PATH_LEN 294
+#endif
+// btla-specific --
+
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_fts_reg =
+{
+ bta_fts_hdl_event,
+ BTA_FtsDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_FtsEnable
+**
+** Description Enable the file transfer server. This function must be
+** called before any other functions in the FTS API are called.
+** When the enable operation is complete the callback function
+** will be called with an BTA_FTS_ENABLE_EVT event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtsEnable(tBTA_SEC sec_mask, const char *p_service_name,
+ const char *p_root_path, BOOLEAN enable_authen,
+ UINT8 realm_len, UINT8 *p_realm,
+ tBTA_FTS_CBACK *p_cback, UINT8 app_id)
+{
+ tBTA_FTS_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_FTS, &bta_fts_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_FTS_API_ENABLE *)GKI_getbuf((UINT16)(sizeof(tBTA_FTS_API_ENABLE) +
+ p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_FTS_API_ENABLE));
+
+ p_buf->p_root_path = (char *)(p_buf + 1);
+ p_buf->p_root_path[p_bta_fs_cfg->max_path_len] = '\0';
+
+ p_buf->hdr.event = BTA_FTS_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->sec_mask = sec_mask;
+ p_buf->app_id = app_id;
+ p_buf->auth_enabled = enable_authen;
+
+ p_buf->realm_len = (realm_len < OBX_MAX_REALM_LEN) ? realm_len :
+ OBX_MAX_REALM_LEN;
+ if (p_realm)
+ memcpy(p_buf->realm, p_realm, p_buf->realm_len);
+
+ if (p_service_name)
+ BCM_STRNCPY_S(p_buf->servicename, sizeof(p_buf->servicename), p_service_name, BTA_SERVICE_NAME_LEN);
+
+ if (p_root_path)
+ {
+ BCM_STRNCPY_S(p_buf->p_root_path, p_bta_fs_cfg->max_path_len+1, p_root_path,
+ p_bta_fs_cfg->max_path_len);
+ p_buf->p_root_path[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtsDisable
+**
+** Description Disable the file transfer server. If the server is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtsDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_FTS);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_FTS_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtsClose
+**
+** Description Close the current connection. This function is called if
+** the phone wishes to close the connection before the FT
+** client disconnects.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtsClose(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_FTS_API_CLOSE_EVT;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtsUnauthRsp
+**
+** Description Sends an OBEX authentication challenge to the connected
+** OBEX client. Called in response to an BTA_FTS_AUTH_EVT event.
+** Used when "enable_authen" is set to TRUE in BTA_FtsEnable().
+**
+** Note: If the "userid_required" is TRUE in the BTA_FTS_AUTH_EVT
+** event, then p_userid is required, otherwise it is optional.
+**
+** p_password must be less than BTA_FTS_MAX_AUTH_KEY_SIZE
+** p_userid must be less than OBX_MAX_REALM_LEN
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtsAuthRsp (char *p_password, char *p_userid)
+{
+ tBTA_FTS_API_AUTHRSP *p_auth_rsp;
+
+ if ((p_auth_rsp = (tBTA_FTS_API_AUTHRSP *)GKI_getbuf(sizeof(tBTA_FTS_API_AUTHRSP))) != NULL)
+ {
+ memset(p_auth_rsp, 0, sizeof(tBTA_FTS_API_AUTHRSP));
+
+ p_auth_rsp->hdr.event = BTA_FTS_API_AUTHRSP_EVT;
+
+ if (p_password)
+ {
+ p_auth_rsp->key_len = strlen(p_password);
+ if (p_auth_rsp->key_len > BTA_FTS_MAX_AUTH_KEY_SIZE)
+ p_auth_rsp->key_len = BTA_FTS_MAX_AUTH_KEY_SIZE;
+ memcpy(p_auth_rsp->key, p_password, p_auth_rsp->key_len);
+ }
+
+ if (p_userid)
+ {
+ p_auth_rsp->userid_len = strlen(p_userid);
+ if (p_auth_rsp->userid_len > OBX_MAX_REALM_LEN)
+ p_auth_rsp->userid_len = OBX_MAX_REALM_LEN;
+ memcpy(p_auth_rsp->userid, p_userid, p_auth_rsp->userid_len);
+ }
+
+ bta_sys_sendmsg(p_auth_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_FtsAccessRsp
+**
+** Description Sends a reply to an access request event (BTA_FTS_ACCESS_EVT).
+** This call MUST be made whenever the event occurs.
+**
+** Parameters oper - operation being accessed.
+** access - BTA_FT_ACCESS_ALLOW or BTA_FT_ACCESS_FORBID
+** p_name - Full path of file to pulled or pushed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_FtsAccessRsp(tBTA_FT_OPER oper, tBTA_FT_ACCESS access, char *p_name)
+{
+ tBTA_FTS_API_ACCESSRSP *p_acc_rsp;
+
+ if ((p_acc_rsp = (tBTA_FTS_API_ACCESSRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_FTS_API_ACCESSRSP)
+ + p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ p_acc_rsp->flag = access;
+ p_acc_rsp->oper = oper;
+ p_acc_rsp->p_name = (char *)(p_acc_rsp + 1);
+ if (p_name)
+ {
+ BCM_STRNCPY_S(p_acc_rsp->p_name, BTA_FS_PATH_LEN, p_name, p_bta_fs_cfg->max_path_len-1);
+ p_acc_rsp->p_name[p_bta_fs_cfg->max_path_len-1] = '\0';
+ }
+ else
+ *p_acc_rsp->p_name = '\0';
+
+ p_acc_rsp->hdr.event = BTA_FTS_API_ACCESSRSP_EVT;
+ bta_sys_sendmsg(p_acc_rsp);
+ }
+}
+#endif /* BTA_FT_INCLUDED */
diff --git a/bta/ft/bta_fts_int.h b/bta/ft/bta_fts_int.h
new file mode 100644
index 0000000..b77c96f
--- /dev/null
+++ b/bta/ft/bta_fts_int.h
@@ -0,0 +1,287 @@
+/*****************************************************************************
+**
+** Name: bta_fts_int.h
+**
+** Description: This is the private file for the file transfer
+** server (FTS).
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_FTS_INT_H
+#define BTA_FTS_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_ft_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#include "bta_ftc_int.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+
+
+#define BTA_FTS_FOLDER_BROWSING_TARGET_UUID "\xF9\xEC\x7B\xC4\x95\x3C\x11\xD2\x98\x4E\x52\x54\x00\xDC\x9E\x09"
+#define BTA_FTS_UUID_LENGTH 16
+#define BTA_FTS_MAX_AUTH_KEY_SIZE 16 /* Must not be greater than OBX_MAX_AUTH_KEY_SIZE */
+
+#define BTA_FTS_DEFAULT_VERSION 0x0100
+#define BTA_FTS_FOLDER_LISTING_TYPE "x-obex/folder-listing"
+
+typedef tOBX_STATUS (tBTA_FTS_OBX_RSP) (tOBX_HANDLE handle, UINT8 rsp_code, BT_HDR *p_pkt);
+
+/* FTS Active ftp obex operation (Valid in connected state) */
+#define FTS_OP_NONE 0
+#define FTS_OP_LISTING 1
+#define FTS_OP_GET_FILE 2
+#define FTS_OP_PUT_FILE 3
+#define FTS_OP_DELETE 4 /* Folder or File */
+#define FTS_OP_CHDIR 5
+#define FTS_OP_MKDIR 6
+#define FTS_OP_RESUME 0x10
+
+/* state machine states */
+enum
+{
+ BTA_FTS_IDLE_ST = 0, /* Idle */
+ BTA_FTS_LISTEN_ST, /* Listen - waiting for OBX/RFC connection */
+ BTA_FTS_W4_AUTH_ST, /* Wait for Authentication - (optional) */
+ BTA_FTS_CONN_ST, /* Connected - FTP Session is active */
+ BTA_FTS_CLOSING_ST /* Closing is in progress */
+};
+
+/* state machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_FTS_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_FTS),
+
+ BTA_FTS_API_AUTHRSP_EVT, /* Response to password request */
+ BTA_FTS_API_ACCESSRSP_EVT, /* Response to an access request */
+ BTA_FTS_API_CLOSE_EVT, /* Disconnect the OBEX channel */
+ BTA_FTS_CI_WRITE_EVT, /* Response to Write request */
+ BTA_FTS_CI_READ_EVT, /* Response to Read request */
+ BTA_FTS_CI_OPEN_EVT, /* Response to File Open request */
+ BTA_FTS_CI_DIRENTRY_EVT, /* Response to a directory entry request */
+ BTA_FTS_OBX_CONN_EVT, /* OBX Channel Connect Request */
+ BTA_FTS_OBX_DISC_EVT, /* OBX Channel Disconnect */
+ BTA_FTS_OBX_ABORT_EVT, /* OBX_operation aborted */
+ BTA_FTS_OBX_PASSWORD_EVT, /* OBX password requested */
+ BTA_FTS_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_FTS_OBX_PUT_EVT, /* Write file data or delete */
+ BTA_FTS_OBX_GET_EVT, /* Read file data or folder listing */
+ BTA_FTS_OBX_SETPATH_EVT, /* Make or Change Directory */
+ BTA_FTS_CI_SESSION_EVT, /* Call-in response to session requests */
+ BTA_FTS_OBX_ACTION_EVT, /* Action command */
+ BTA_FTS_APPL_TOUT_EVT, /* Timeout waiting for application */
+ BTA_FTS_DISC_ERR_EVT, /* Sends OBX_DisconnectRsp with error code */
+ BTA_FTS_GASP_ERR_EVT, /* Sends Err Resp to Get, Abort, Setpath, and Put */
+ BTA_FTS_CLOSE_CMPL_EVT, /* Finished closing channel */
+ BTA_FTS_DISABLE_CMPL_EVT, /* Finished disabling server */
+
+ /* these events are handled outside the state machine */
+ BTA_FTS_API_ENABLE_EVT
+};
+
+typedef UINT16 tBTA_FTS_INT_EVT;
+
+typedef UINT8 tBTA_FTS_STATE;
+
+/* data type for BTA_FTS_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_FTS_CBACK *p_cback;
+ char servicename[BTA_SERVICE_NAME_LEN + 1];
+ char *p_root_path;
+ UINT8 realm [OBX_MAX_REALM_LEN]; /* The realm is intended to be
+ displayed to users so they know
+ which userid and password to use.
+ The first byte of the string is
+ the character set of the string.
+ */
+ UINT8 realm_len;
+ UINT8 sec_mask;
+ UINT8 app_id;
+ BOOLEAN auth_enabled;
+} tBTA_FTS_API_ENABLE;
+
+/* data type for BTA_FTS_API_AUTHRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 key [BTA_FTS_MAX_AUTH_KEY_SIZE]; /* The authentication key.*/
+ UINT8 key_len;
+ UINT8 userid [OBX_MAX_REALM_LEN]; /* The authentication user id.*/
+ UINT8 userid_len;
+} tBTA_FTS_API_AUTHRSP;
+
+/* data type for BTA_FTS_API_ACCESSRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_name;
+ tBTA_FT_OPER oper;
+ tBTA_FT_ACCESS flag;
+} tBTA_FTS_API_ACCESSRSP;
+
+/* data type for all obex events
+ hdr.event contains the FTS event
+*/
+typedef struct
+{
+ BT_HDR hdr;
+ tOBX_HANDLE handle;
+ tOBX_EVT_PARAM param;
+ BT_HDR *p_pkt;
+ tOBX_EVENT obx_event;
+ UINT8 rsp_code;
+} tBTA_FTS_OBX_EVENT;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_FTS_API_ENABLE api_enable;
+ tBTA_FTS_API_AUTHRSP auth_rsp;
+ tBTA_FTS_API_ACCESSRSP access_rsp;
+ tBTA_FTS_OBX_EVENT obx_evt;
+ tBTA_FS_CI_GETDIR_EVT getdir_evt;
+ tBTA_FS_CI_OPEN_EVT open_evt;
+ tBTA_FS_CI_RESUME_EVT resume_evt;
+ tBTA_FS_CI_READ_EVT read_evt;
+ tBTA_FS_CI_WRITE_EVT write_evt;
+} tBTA_FTS_DATA;
+
+
+/* OBX Response Packet Structure - Holds current response packet info */
+typedef struct
+{
+ BT_HDR *p_pkt; /* (Get/Put) Holds the current OBX header for Put or Get */
+ UINT8 *p_start; /* (Get/Put) Start of the Body of the packet */
+ UINT16 offset; /* (Get/Put) Contains the current offset into the Body (p_start) */
+ UINT16 bytes_left; /* (Get/Put) Holds bytes available left in Obx packet */
+ BOOLEAN final_pkt; /* (Put) Holds the final bit of the Put packet */
+} tBTA_FTS_OBX_PKT;
+
+/* Directory Listing Information */
+typedef struct
+{
+ tBTA_FS_DIRENTRY *p_entry; /* Holds current directory entry */
+ BOOLEAN is_root; /* TRUE if path is root directory */
+} tBTA_FTS_DIRLIST;
+
+/* Power management state for FTS */
+#define BTA_FTS_PM_BUSY 0
+#define BTA_FTS_PM_IDLE 1
+
+/* FTS control block */
+typedef struct
+{
+ tBTA_FTS_CBACK *p_cback; /* pointer to application callback function */
+ char *p_name; /* Holds name of current operation */
+ char *p_dest; /* Holds p_dest_name of current operation */
+ char *p_path; /* Holds path of current operation */
+ char *p_rootpath;
+ char *p_workdir; /* Current working directory */
+ tBTA_FTS_OBX_PKT obx; /* Holds the current OBX packet information */
+ tBTA_FTS_DIRLIST dir; /* Holds current directory list information */
+ UINT32 sdp_handle; /* SDP record handle */
+ UINT32 file_length; /* length of file being PUT/GET */
+ UINT8 sess_id[OBX_SESSION_ID_SIZE]; /* session id */
+ int fd; /* File Descriptor of opened file */
+ BD_ADDR bd_addr; /* Device currently connected to */
+ tOBX_HANDLE obx_handle;
+ UINT16 peer_mtu;
+ UINT16 psm; /* PSM for Obex Over L2CAP */
+ UINT8 perms[BTA_FS_PERM_SIZE]; /* the permission */
+ UINT8 scn; /* SCN of the FTP server */
+ tBTA_FTS_STATE state; /* state machine state */
+ UINT8 obx_oper; /* current active OBX operation PUT FILE, GET FILE, LISTING, etc */
+ UINT8 app_id;
+ BOOLEAN auth_enabled; /* Is OBEX authentication enabled */
+ BOOLEAN cout_active; /* TRUE when waiting for a call-in function */
+ tBTA_FT_OPER acc_active; /* op code when waiting for an access rsp (API) (0 not active) */
+ BOOLEAN suspending; /* TRUE when suspending session */
+ UINT8 resume_ssn; /* the ssn for resume session */
+ BOOLEAN disabling; /* TRUE when disabling server */
+ UINT8 pm_state; /* power management state */
+} tBTA_FTS_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* FTS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_FTS_CB bta_fts_cb;
+#else
+extern tBTA_FTS_CB *bta_fts_cb_ptr;
+#define bta_fts_cb (*bta_fts_cb_ptr)
+#endif
+
+/* FT configuration constants */
+extern tBTA_FT_CFG * p_bta_ft_cfg;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern BOOLEAN bta_fts_hdl_event(BT_HDR *p_msg);
+extern void bta_fts_sm_execute(tBTA_FTS_CB *p_cb, UINT16 event, tBTA_FTS_DATA *p_data);
+extern void bta_fts_sdp_register (tBTA_FTS_CB *p_cb, char *p_service_name);
+extern void bta_fts_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt);
+
+/* action functions */
+extern void bta_fts_api_disable(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_api_authrsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_api_accessrsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_api_close(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_ci_write(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_ci_read(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_ci_open(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_ci_resume(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_ci_direntry(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_connect(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_disc(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_close(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_abort(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_password(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_put(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_get(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_setpath(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_obx_action(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_appl_tout(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_conn_err_rsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_disc_err_rsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_gasp_err_rsp(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_close_complete(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_disable_cmpl(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+extern void bta_fts_session_req(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+
+/* object store */
+extern UINT8 bta_fts_mkdir(BT_HDR *p_pkt, tBTA_FT_OPER *p_op);
+extern UINT8 bta_fts_chdir(BT_HDR *p_pkt, BOOLEAN backup_flag, tBTA_FT_OPER *p_op);
+extern void bta_fts_getdirlist(char *p_name);
+extern void bta_fts_proc_get_file(char *p_name);
+extern void bta_fts_proc_put_file(BT_HDR *p_pkt, char *p_name, BOOLEAN final_pkt, UINT8 oper);
+extern void bta_fts_delete(tBTA_FTS_OBX_EVENT *p_evt, const char *p);
+extern void bta_fts_req_app_access (tBTA_FT_OPER oper, tBTA_FTS_CB *p_cb);
+
+/* miscellaneous functions */
+extern void bta_fts_get_file_rsp(UINT8 rsp_code, UINT16 num_read);
+extern void bta_fts_put_file_rsp(UINT8 rsp_code);
+extern void bta_fts_end_of_list(UINT8 rsp_code);
+extern UINT8 bta_fts_add_list_entry(void);
+extern void bta_fts_clean_list(tBTA_FTS_CB *p_cb);
+extern void bta_fts_clean_getput(tBTA_FTS_CB *p_cb, BOOLEAN is_aborted);
+extern void bta_fts_disable_cleanup(tBTA_FTS_CB *p_cb);
+extern void bta_fts_discard_data(UINT16 event, tBTA_FTS_DATA *p_data);
+
+#endif /* BTA_FTS_INT_H */
diff --git a/bta/ft/bta_fts_main.c b/bta/ft/bta_fts_main.c
new file mode 100644
index 0000000..67be954
--- /dev/null
+++ b/bta/ft/bta_fts_main.c
@@ -0,0 +1,603 @@
+/*****************************************************************************
+**
+** Name: bta_fts_main.c
+**
+** Description: This file contains the file transfer server main functions
+** and state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(BTA_FT_INCLUDED) && (BTA_FT_INCLUDED == TRUE)
+
+#include "bta_fs_api.h"
+#include "bta_fts_int.h"
+#include "gki.h"
+#include "utl.h"
+#include "obx_api.h"
+#include "rfcdefs.h" /* BT_PSM_RFCOMM */
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_FTS_API_DISABLE,
+ BTA_FTS_API_AUTHRSP,
+ BTA_FTS_API_ACCESSRSP,
+ BTA_FTS_API_CLOSE,
+ BTA_FTS_CI_WRITE,
+ BTA_FTS_CI_READ,
+ BTA_FTS_CI_OPEN,
+ BTA_FTS_CI_DIRENTRY,
+ BTA_FTS_OBX_CONNECT,
+ BTA_FTS_OBX_DISC,
+ BTA_FTS_OBX_CLOSE,
+ BTA_FTS_OBX_ABORT,
+ BTA_FTS_OBX_PASSWORD,
+ BTA_FTS_OBX_PUT,
+ BTA_FTS_OBX_GET,
+ BTA_FTS_OBX_SETPATH,
+ BTA_FTS_CI_RESUME,
+ BTA_FTS_OBX_ACTION,
+ BTA_FTS_SESSION_REQ,
+ BTA_FTS_APPL_TOUT,
+ BTA_FTS_CONN_ERR_RSP,
+ BTA_FTS_DISC_ERR_RSP,
+ BTA_FTS_GASP_ERR_RSP,
+ BTA_FTS_CLOSE_COMPLETE,
+ BTA_FTS_DISABLE_CMPL,
+ BTA_FTS_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_FTS_ACTION)(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data);
+
+/* action function list */
+const tBTA_FTS_ACTION bta_fts_action[] =
+{
+ bta_fts_api_disable,
+ bta_fts_api_authrsp,
+ bta_fts_api_accessrsp,
+ bta_fts_api_close,
+ bta_fts_ci_write,
+ bta_fts_ci_read,
+ bta_fts_ci_open,
+ bta_fts_ci_direntry,
+ bta_fts_obx_connect,
+ bta_fts_obx_disc,
+ bta_fts_obx_close,
+ bta_fts_obx_abort,
+ bta_fts_obx_password,
+ bta_fts_obx_put,
+ bta_fts_obx_get,
+ bta_fts_obx_setpath,
+ bta_fts_ci_resume,
+ bta_fts_obx_action,
+ bta_fts_session_req,
+ bta_fts_appl_tout,
+ bta_fts_conn_err_rsp,
+ bta_fts_disc_err_rsp,
+ bta_fts_gasp_err_rsp,
+ bta_fts_close_complete,
+ bta_fts_disable_cmpl
+};
+
+
+/* state table information */
+#define BTA_FTS_ACTIONS 1 /* number of actions */
+#define BTA_FTS_NEXT_STATE 1 /* position of next state */
+#define BTA_FTS_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_fts_st_idle[][BTA_FTS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_FTS_API_ENABLE_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_API_AUTHRSP_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_API_ACCESSRSP_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_API_CLOSE_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_CI_WRITE_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_CI_READ_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_CI_OPEN_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_CI_DIRENTRY_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_OBX_CONN_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_OBX_DISC_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_OBX_ABORT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_OBX_PASSWORD_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_OBX_CLOSE_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_OBX_PUT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_OBX_GET_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_OBX_SETPATH_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_CI_SESSION_EVT */ {BTA_FTS_CI_RESUME, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_ACTION_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_APPL_TOUT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_DISC_ERR_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_GASP_ERR_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_CLOSE_CMPL_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST},
+/* BTA_FTS_DISABLE_CMPL_EVT */ {BTA_FTS_IGNORE, BTA_FTS_IDLE_ST}
+};
+
+/* state table for obex/rfcomm connection state */
+static const UINT8 bta_fts_st_listen[][BTA_FTS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_FTS_API_DISABLE_EVT */ {BTA_FTS_API_DISABLE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_API_AUTHRSP_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_API_ACCESSRSP_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_API_CLOSE_EVT */ {BTA_FTS_API_CLOSE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CI_WRITE_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CI_READ_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CI_OPEN_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CI_DIRENTRY_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_CONN_EVT */ {BTA_FTS_OBX_CONNECT, BTA_FTS_CONN_ST},
+/* BTA_FTS_OBX_DISC_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_ABORT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_PASSWORD_EVT */ {BTA_FTS_OBX_PASSWORD, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_CLOSE_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_PUT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_GET_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_SETPATH_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CI_SESSION_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_ACTION_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_APPL_TOUT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_DISC_ERR_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_GASP_ERR_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CLOSE_CMPL_EVT */ {BTA_FTS_IGNORE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_DISABLE_CMPL_EVT */ {BTA_FTS_DISABLE_CMPL, BTA_FTS_IDLE_ST}
+};
+
+/* state table for wait for authentication response state */
+static const UINT8 bta_fts_st_w4_auth[][BTA_FTS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_FTS_API_DISABLE_EVT */ {BTA_FTS_API_DISABLE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_API_AUTHRSP_EVT */ {BTA_FTS_API_AUTHRSP, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_API_ACCESSRSP_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_API_CLOSE_EVT */ {BTA_FTS_API_CLOSE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_CI_WRITE_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_CI_READ_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_CI_OPEN_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_CI_DIRENTRY_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_CONN_EVT */ {BTA_FTS_CONN_ERR_RSP, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_DISC_EVT */ {BTA_FTS_OBX_DISC, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_ABORT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_PASSWORD_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_CLOSE_EVT */ {BTA_FTS_OBX_CLOSE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_PUT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_GET_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_SETPATH_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_CI_SESSION_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_ACTION_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_APPL_TOUT_EVT */ {BTA_FTS_APPL_TOUT, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_DISC_ERR_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_GASP_ERR_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_CLOSE_CMPL_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_DISABLE_CMPL_EVT */ {BTA_FTS_DISABLE_CMPL, BTA_FTS_IDLE_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_fts_st_connected[][BTA_FTS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_FTS_API_DISABLE_EVT */ {BTA_FTS_API_DISABLE, BTA_FTS_CONN_ST},
+/* BTA_FTS_API_AUTHRSP_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CONN_ST},
+/* BTA_FTS_API_ACCESSRSP_EVT */ {BTA_FTS_API_ACCESSRSP, BTA_FTS_CONN_ST},
+/* BTA_FTS_API_CLOSE_EVT */ {BTA_FTS_API_CLOSE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_CI_WRITE_EVT */ {BTA_FTS_CI_WRITE, BTA_FTS_CONN_ST},
+/* BTA_FTS_CI_READ_EVT */ {BTA_FTS_CI_READ, BTA_FTS_CONN_ST},
+/* BTA_FTS_CI_OPEN_EVT */ {BTA_FTS_CI_OPEN, BTA_FTS_CONN_ST},
+/* BTA_FTS_CI_DIRENTRY_EVT */ {BTA_FTS_CI_DIRENTRY, BTA_FTS_CONN_ST},
+/* BTA_FTS_OBX_CONN_EVT */ {BTA_FTS_SESSION_REQ, BTA_FTS_CONN_ST},
+/* BTA_FTS_OBX_DISC_EVT */ {BTA_FTS_OBX_DISC, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_ABORT_EVT */ {BTA_FTS_OBX_ABORT, BTA_FTS_CONN_ST},
+/* BTA_FTS_OBX_PASSWORD_EVT */ {BTA_FTS_IGNORE, BTA_FTS_W4_AUTH_ST},
+/* BTA_FTS_OBX_CLOSE_EVT */ {BTA_FTS_OBX_CLOSE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_PUT_EVT */ {BTA_FTS_OBX_PUT, BTA_FTS_CONN_ST},
+/* BTA_FTS_OBX_GET_EVT */ {BTA_FTS_OBX_GET, BTA_FTS_CONN_ST},
+/* BTA_FTS_OBX_SETPATH_EVT */ {BTA_FTS_OBX_SETPATH, BTA_FTS_CONN_ST},
+/* BTA_FTS_CI_SESSION_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CONN_ST},
+/* BTA_FTS_OBX_ACTION_EVT */ {BTA_FTS_OBX_ACTION, BTA_FTS_CONN_ST},
+/* BTA_FTS_APPL_TOUT_EVT */ {BTA_FTS_APPL_TOUT, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_DISC_ERR_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CONN_ST},
+/* BTA_FTS_GASP_ERR_EVT */ {BTA_FTS_GASP_ERR_RSP, BTA_FTS_CONN_ST},
+/* BTA_FTS_CLOSE_CMPL_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CONN_ST},
+/* BTA_FTS_DISABLE_CMPL_EVT */ {BTA_FTS_DISABLE_CMPL, BTA_FTS_IDLE_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_fts_st_closing[][BTA_FTS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_FTS_API_DISABLE_EVT */ {BTA_FTS_API_DISABLE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_API_AUTHRSP_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_API_ACCESSRSP_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_API_CLOSE_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_CI_WRITE_EVT */ {BTA_FTS_CLOSE_COMPLETE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CI_READ_EVT */ {BTA_FTS_CLOSE_COMPLETE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CI_OPEN_EVT */ {BTA_FTS_CLOSE_COMPLETE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_CI_DIRENTRY_EVT */ {BTA_FTS_CLOSE_COMPLETE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_OBX_CONN_EVT */ {BTA_FTS_SESSION_REQ, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_DISC_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_ABORT_EVT */ {BTA_FTS_OBX_ABORT, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_PASSWORD_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_CLOSE_EVT */ {BTA_FTS_OBX_CLOSE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_PUT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_GET_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_SETPATH_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_CI_SESSION_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_OBX_ACTION_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_APPL_TOUT_EVT */ {BTA_FTS_IGNORE, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_DISC_ERR_EVT */ {BTA_FTS_DISC_ERR_RSP, BTA_FTS_CONN_ST},
+/* BTA_FTS_GASP_ERR_EVT */ {BTA_FTS_GASP_ERR_RSP, BTA_FTS_CLOSING_ST},
+/* BTA_FTS_CLOSE_CMPL_EVT */ {BTA_FTS_CLOSE_COMPLETE, BTA_FTS_LISTEN_ST},
+/* BTA_FTS_DISABLE_CMPL_EVT */ {BTA_FTS_DISABLE_CMPL, BTA_FTS_IDLE_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_FTS_ST_TBL)[BTA_FTS_NUM_COLS];
+
+/* state table */
+const tBTA_FTS_ST_TBL bta_fts_st_tbl[] =
+{
+ bta_fts_st_idle,
+ bta_fts_st_listen,
+ bta_fts_st_w4_auth,
+ bta_fts_st_connected,
+ bta_fts_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* FTS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_FTS_CB bta_fts_cb;
+#endif
+
+#if BTA_FTS_DEBUG == TRUE
+static char *fts_evt_code(tBTA_FTS_INT_EVT evt_code);
+static char *fts_state_code(tBTA_FTS_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_fts_sm_execute
+**
+** Description State machine event handling function for FTS
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_sm_execute(tBTA_FTS_CB *p_cb, UINT16 event, tBTA_FTS_DATA *p_data)
+{
+ tBTA_FTS_ST_TBL state_table;
+ UINT8 action;
+ int i;
+#if BTA_FTS_DEBUG == TRUE
+ tBTA_FTS_STATE in_state = bta_fts_cb.state;
+ UINT16 in_event = event;
+ APPL_TRACE_EVENT3("FTS Event : State 0x%02x [%s], Event [%s]", in_state,
+ fts_state_code(in_state),
+ fts_evt_code(event));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_fts_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_FTS_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_FTS_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_FTS_IGNORE)
+ {
+ (*bta_fts_action[action])(p_cb, p_data);
+ }
+ else
+ {
+ /* discard fts data */
+ bta_fts_discard_data(p_data->hdr.event, p_data);
+ break;
+ }
+ }
+
+#if BTA_FTS_DEBUG == TRUE
+ if (in_state != bta_fts_cb.state)
+ {
+ APPL_TRACE_DEBUG3("FTS State Change: [%s] -> [%s] after Event [%s]",
+ fts_state_code(in_state),
+ fts_state_code(bta_fts_cb.state),
+ fts_evt_code(in_event));
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_api_enable
+**
+** Description Handle an api enable event. This function enables the FT
+** Server by opening an Obex/Rfcomm channel and placing it into
+** listen mode.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_fts_api_enable(tBTA_FTS_CB *p_cb, tBTA_FTS_DATA *p_data)
+{
+ tOBX_StartParams start_msg;
+ tBTA_FTS_API_ENABLE *p_api = &p_data->api_enable;
+ tOBX_TARGET target;
+ UINT16 len;
+ tOBX_STATUS status;
+ UINT16 mtu = OBX_MAX_MTU;
+
+ /* initialize control block */
+ memset(p_cb, 0, sizeof(tBTA_FTS_CB));
+
+ /* Allocate an aligned memory buffer to hold the root path and working directory */
+ /* Add 1 byte for '\0' */
+ len = p_bta_fs_cfg->max_path_len + 1;
+ if ((p_cb->p_rootpath = (char *)GKI_getbuf((UINT16)(len * 2))) != NULL)
+ {
+ p_cb->p_workdir = p_cb->p_rootpath + len;
+ memcpy(target.target, BTA_FTS_FOLDER_BROWSING_TARGET_UUID, BTA_FTS_UUID_LENGTH);
+ target.len = BTA_FTS_UUID_LENGTH;
+
+ /* store parameters */
+ p_cb->app_id = p_api->app_id;
+ p_cb->p_cback = p_api->p_cback;
+ p_cb->scn = BTM_AllocateSCN();
+
+ if (p_bta_ft_cfg->over_l2cap)
+ {
+ p_cb->psm = L2CA_AllocatePSM();
+ BTM_SetSecurityLevel (FALSE, p_api->servicename, BTM_SEC_SERVICE_OBEX_FTP,
+ p_api->sec_mask, p_cb->psm,
+ 0, 0);
+ }
+
+ p_cb->auth_enabled = p_api->auth_enabled;
+
+ p_cb->fd = BTA_FS_INVALID_FD;
+ /* Initialize the current working directory to be the root directory */
+ BCM_STRNCPY_S(p_cb->p_rootpath, len, p_api->p_root_path, len-1);
+ BCM_STRNCPY_S(p_cb->p_workdir, len, p_api->p_root_path, len-1);
+
+ /* Register FTP security requirements with BTM */
+ BTM_SetSecurityLevel(FALSE, p_api->servicename, BTM_SEC_SERVICE_OBEX_FTP,
+ p_api->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, (UINT32)p_cb->scn);
+
+ /* Start up the FTP service */
+ memset (&start_msg, 0, sizeof(tOBX_StartParams));
+ start_msg.p_target = &target;
+
+ /* Make the MTU fit into one RFC frame */
+ start_msg.mtu = mtu;
+ start_msg.scn = p_cb->scn;
+ start_msg.psm = p_cb->psm;
+ start_msg.srm = p_bta_ft_cfg->srm;
+ start_msg.nonce = p_bta_ft_cfg->nonce;
+ start_msg.max_suspend = p_bta_ft_cfg->max_suspend;
+ start_msg.authenticate = p_cb->auth_enabled;
+
+ start_msg.auth_option = (p_bta_ft_cfg->userid_req) ? OBX_AO_USR_ID : OBX_AO_NONE;
+ start_msg.p_cback = bta_fts_obx_cback;
+
+ start_msg.realm_len = p_api->realm_len;
+ start_msg.p_realm = p_api->realm;
+ start_msg.realm_charset = (tOBX_CHARSET) p_bta_ft_cfg->realm_charset;
+
+ if ((status = OBX_StartServer (&start_msg, &p_cb->obx_handle)) == OBX_SUCCESS)
+ {
+ /* Set up the SDP record for file transfer service */
+ bta_fts_sdp_register(p_cb, p_api->servicename);
+
+ if (start_msg.nonce)
+ {
+ bta_fs_co_resume (BTA_FTS_CI_SESSION_EVT, p_cb->app_id);
+ }
+ else
+ {
+ p_data->resume_evt.status = BTA_FS_CO_FAIL;
+ bta_fts_ci_resume(p_cb, p_data);
+ }
+ }
+ else
+ APPL_TRACE_ERROR1("OBX_StartServer returns error (%d)", status);
+ }
+ else /* Cannot allocate resources to run Server */
+ APPL_TRACE_ERROR0("Not enough Resources to run FTP Server");
+
+ p_cb->p_cback(BTA_FTS_ENABLE_EVT, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_hdl_event
+**
+** Description File transfer server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_fts_hdl_event(BT_HDR *p_msg)
+{
+#if BTA_FTS_DEBUG == TRUE
+ tBTA_FTS_STATE in_state = bta_fts_cb.state;
+#endif
+
+ switch (p_msg->event)
+ {
+ case BTA_FTS_API_ENABLE_EVT:
+#if BTA_FTS_DEBUG == TRUE
+ APPL_TRACE_EVENT3("FTS Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ fts_state_code(in_state),
+ fts_evt_code(p_msg->event));
+#endif
+ bta_fts_api_enable(&bta_fts_cb, (tBTA_FTS_DATA *) p_msg);
+
+#if BTA_FTS_DEBUG == TRUE
+ if (in_state != bta_fts_cb.state)
+ {
+ APPL_TRACE_DEBUG3("FTS State Change: [%s] -> [%s] after Event [%s]",
+ fts_state_code(in_state),
+ fts_state_code(bta_fts_cb.state),
+ fts_evt_code(p_msg->event));
+ }
+#endif
+ break;
+
+ default:
+
+ bta_fts_sm_execute(&bta_fts_cb, p_msg->event, (tBTA_FTS_DATA *) p_msg);
+
+ if ( bta_fts_cb.state == BTA_FTS_CONN_ST )
+ {
+ if (( bta_fts_cb.pm_state == BTA_FTS_PM_IDLE )
+ &&( bta_fts_cb.obx_oper != FTS_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA FTS informs DM/PM busy state");
+ bta_sys_busy( BTA_ID_FTS ,bta_fts_cb.app_id, bta_fts_cb.bd_addr);
+ bta_fts_cb.pm_state = BTA_FTS_PM_BUSY;
+ }
+ else if (( bta_fts_cb.pm_state == BTA_FTS_PM_BUSY )
+ &&( bta_fts_cb.obx_oper == FTS_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA FTS informs DM/PM idle state");
+ bta_sys_idle( BTA_ID_FTS ,bta_fts_cb.app_id, bta_fts_cb.bd_addr);
+ bta_fts_cb.pm_state = BTA_FTS_PM_IDLE;
+ }
+ }
+ else if ( bta_fts_cb.state == BTA_FTS_LISTEN_ST )
+ {
+ /* initialize power management state */
+ bta_fts_cb.pm_state = BTA_FTS_PM_BUSY;
+ }
+
+ break;
+ }
+
+ return (TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_FTS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function fts_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *fts_evt_code(tBTA_FTS_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_FTS_API_DISABLE_EVT:
+ return "BTA_FTS_API_DISABLE_EVT";
+ case BTA_FTS_API_AUTHRSP_EVT:
+ return "BTA_FTS_API_AUTHRSP_EVT";
+ case BTA_FTS_API_ACCESSRSP_EVT:
+ return "BTA_FTS_API_ACCESSRSP_EVT";
+ case BTA_FTS_API_CLOSE_EVT:
+ return "BTA_FTS_API_CLOSE_EVT";
+ case BTA_FTS_CI_WRITE_EVT:
+ return "BTA_FTS_CI_WRITE_EVT";
+ case BTA_FTS_CI_READ_EVT:
+ return "BTA_FTS_CI_READ_EVT";
+ case BTA_FTS_CI_OPEN_EVT:
+ return "BTA_FTS_CI_OPEN_EVT";
+ case BTA_FTS_CI_DIRENTRY_EVT:
+ return "BTA_FTS_CI_DIRENTRY_EVT";
+ case BTA_FTS_OBX_CONN_EVT:
+ return "BTA_FTS_OBX_CONN_EVT";
+ case BTA_FTS_OBX_DISC_EVT:
+ return "BTA_FTS_OBX_DISC_EVT";
+ case BTA_FTS_OBX_ABORT_EVT:
+ return "BTA_FTS_OBX_ABORT_EVT";
+ case BTA_FTS_OBX_PASSWORD_EVT:
+ return "BTA_FTS_OBX_PASSWORD_EVT";
+ case BTA_FTS_OBX_CLOSE_EVT:
+ return "BTA_FTS_OBX_CLOSE_EVT";
+ case BTA_FTS_OBX_PUT_EVT:
+ return "BTA_FTS_OBX_PUT_EVT";
+ case BTA_FTS_OBX_GET_EVT:
+ return "BTA_FTS_OBX_GET_EVT";
+ case BTA_FTS_OBX_SETPATH_EVT:
+ return "BTA_FTS_OBX_SETPATH_EVT";
+ case BTA_FTS_OBX_ACTION_EVT:
+ return "BTA_FTS_OBX_ACTION_EVT";
+ case BTA_FTS_CI_SESSION_EVT:
+ return "BTA_FTS_CI_SESSION_EVT";
+ case BTA_FTS_APPL_TOUT_EVT:
+ return "BTA_FTS_APPL_TOUT_EVT";
+ case BTA_FTS_DISC_ERR_EVT:
+ return "BTA_FTS_DISC_ERR_EVT";
+ case BTA_FTS_GASP_ERR_EVT:
+ return "BTA_FTS_GASP_ERR_EVT";
+ case BTA_FTS_API_ENABLE_EVT:
+ return "BTA_FTS_API_ENABLE_EVT";
+ case BTA_FTS_CLOSE_CMPL_EVT:
+ return "BTA_FTS_CLOSE_CMPL_EVT";
+ case BTA_FTS_DISABLE_CMPL_EVT:
+ return "BTA_FTS_DISABLE_CMPL_EVT";
+ default:
+ return "unknown FTS event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function fts_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *fts_state_code(tBTA_FTS_STATE state_code)
+{
+ switch(state_code)
+ {
+ case BTA_FTS_IDLE_ST:
+ return "BTA_FTS_IDLE_ST";
+ case BTA_FTS_LISTEN_ST:
+ return "BTA_FTS_LISTEN_ST";
+ case BTA_FTS_W4_AUTH_ST:
+ return "BTA_FTS_W4_AUTH_ST";
+ case BTA_FTS_CONN_ST:
+ return "BTA_FTS_CONN_ST";
+ case BTA_FTS_CLOSING_ST:
+ return "BTA_FTS_CLOSING_ST";
+ default:
+ return "unknown FTS state code";
+ }
+}
+
+#endif /* Debug Functions */
+#endif /* BTA_FT_INCLUDED */
diff --git a/bta/ft/bta_fts_sdp.c b/bta/ft/bta_fts_sdp.c
new file mode 100644
index 0000000..2613942
--- /dev/null
+++ b/bta/ft/bta_fts_sdp.c
@@ -0,0 +1,66 @@
+/*****************************************************************************
+**
+** Name: bta_fts_sdp.c
+**
+** File: Implements the SDP functions used by File Transfer Server
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <string.h>
+
+#include "sdp_api.h"
+#include "bta_fts_int.h"
+#include "goep_util.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+
+/*****************************************************************************
+**
+** Function: bta_fts_sdp_register()
+**
+** Purpose: Registers the File Transfer service with SDP
+**
+** Parameters:
+**
+**
+** Returns: void
+**
+*****************************************************************************/
+void bta_fts_sdp_register (tBTA_FTS_CB *p_cb, char *p_service_name)
+{
+ UINT16 ftp_service = UUID_SERVCLASS_OBEX_FILE_TRANSFER;
+ tGOEP_ERRORS status = GOEP_ERROR;
+ UINT16 version = BTA_FTS_DEFAULT_VERSION;
+ UINT8 temp[4], *p;
+
+ if (p_bta_ft_cfg->over_l2cap)
+ {
+ version = BTA_FT_ENHANCED_VERSION;
+ }
+ status = GOEP_Register (p_service_name, &p_cb->sdp_handle, p_cb->scn, 1, &ftp_service,
+ ftp_service, version);
+
+ if (status == GOEP_SUCCESS)
+ {
+ if (p_bta_ft_cfg->over_l2cap)
+ {
+ /* add the psm */
+ p = temp;
+ UINT16_TO_BE_STREAM(p, p_cb->psm);
+ SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_OBX_OVR_L2CAP_PSM, UINT_DESC_TYPE,
+ (UINT32)2, (UINT8*)temp);
+ }
+
+
+ bta_sys_add_uuid(ftp_service); /* UUID_SERVCLASS_OBEX_FILE_TRANSFER */
+ APPL_TRACE_DEBUG1("FTS: SDP Registered (handle 0x%08x)", p_cb->sdp_handle);
+ }
+
+ return;
+}
diff --git a/bta/ft/bta_fts_utils.c b/bta/ft/bta_fts_utils.c
new file mode 100644
index 0000000..f689752
--- /dev/null
+++ b/bta/ft/bta_fts_utils.c
@@ -0,0 +1,972 @@
+/*****************************************************************************
+**
+** Name: bta_fts_utils.c
+**
+** Description: This file implements object store functions for the
+** file transfer server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_FT_INCLUDED) && (BTA_FT_INCLUDED == TRUE)
+
+#include <stdio.h>
+#include <string.h>
+#include "bta_fs_api.h"
+#include "bta_fts_int.h"
+#include "bta_fs_co.h"
+#include "gki.h"
+#include "utl.h"
+
+/*******************************************************************************
+** Constants
+*******************************************************************************/
+
+/*******************************************************************************
+** Local Function Prototypes
+*******************************************************************************/
+
+/*******************************************************************************
+* Macros for FTS
+*******************************************************************************/
+#define BTA_FTS_XML_EOL "\n"
+#define BTA_FTS_FOLDER_LISTING_START ( "<?xml version=\"1.0\"?>\n" \
+ "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">\n" \
+ "<folder-listing version=\"1.0\">\n" )
+
+#define BTA_FTS_FOLDER_LISTING_END ( "</folder-listing>" )
+#define BTA_FTS_PARENT_FOLDER (" <parent-folder/>\n")
+
+#define BTA_FTS_FILE_ELEM "file"
+#define BTA_FTS_FOLDER_ELEM "folder"
+#define BTA_FTS_NAME_ATTR "name"
+#define BTA_FTS_SIZE_ATTR "size"
+#define BTA_FTS_TYPE_ATTR "type"
+#define BTA_FTS_MODIFIED_ATTR "modified"
+#define BTA_FTS_CREATED_ATTR "created"
+#define BTA_FTS_ACCESSED_ATTR "accessed"
+#define BTA_FTS_USER_PERM_ATTR "user-perm"
+
+/*******************************************************************************
+* Exported Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_fts_getdirlist
+**
+** Description Processes the retrieval of a directory listing.
+**
+** Parameters p_pkt - Pointer to the OBX Get request
+** name directory to list.
+**
+**
+** Returns UINT8 - OBX response code. OBX_RSP_OK if initiated.
+**
+*******************************************************************************/
+void bta_fts_getdirlist(char *p_name)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTS_DIRLIST *p_dir = &p_cb->dir;
+ UINT16 temp_len;
+ BOOLEAN is_dir;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+ if (!p_cb->p_path)
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1));
+ if (p_cb->p_path)
+ {
+ /* If not specified, use the current work directory */
+ if (!p_name || p_name[0] == '\0')
+ {
+ p_cb->p_path[p_bta_fs_cfg->max_path_len] = 0;
+ BCM_STRNCPY_S(p_cb->p_path, (p_bta_fs_cfg->max_path_len + 1), p_cb->p_workdir, p_bta_fs_cfg->max_path_len);
+ }
+ else
+ {
+ if ((strlen(p_cb->p_workdir) + strlen(p_name) + 2) <= p_bta_fs_cfg->max_path_len)
+ {
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+
+ /* Make sure the Name is a directory and accessible */
+ if (((bta_fs_co_access(p_cb->p_path, BTA_FS_ACC_EXIST,
+ &is_dir, p_cb->app_id))!= BTA_FS_CO_OK)
+ || !is_dir)
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+
+ /* Build the listing */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ if (!(strcmp(p_cb->p_path, p_cb->p_rootpath)))
+ p_dir->is_root = TRUE;
+ else
+ p_dir->is_root = FALSE;
+
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle, p_cb->peer_mtu);
+
+ if (!p_dir->p_entry)
+ {
+ /* Allocate enough space for the structure and the file name */
+ if ((p_dir->p_entry = (tBTA_FS_DIRENTRY *)
+ GKI_getbuf((UINT16)(sizeof(tBTA_FS_DIRENTRY) +
+ p_bta_fs_cfg->max_file_len + 1))) != NULL)
+ p_dir->p_entry->p_name = (char *)(p_dir->p_entry + 1);
+ }
+
+ if (p_dir->p_entry && p_obx->p_pkt)
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ /* Is this a new request or continuation? */
+ if ((p_cb->obx_oper == FTS_OP_NONE))
+ {
+ p_cb->obx_oper = FTS_OP_LISTING;
+ APPL_TRACE_EVENT1("FTS List Directory: Name [%s]", p_cb->p_path);
+
+ temp_len = strlen(BTA_FTS_FOLDER_LISTING_START);
+
+ /* Add the beginning label of http */
+ memcpy(p_obx->p_start, BTA_FTS_FOLDER_LISTING_START, temp_len);
+ p_obx->bytes_left -= (UINT16)(temp_len + strlen(BTA_FTS_FOLDER_LISTING_END));
+ p_obx->offset += temp_len;
+
+ /* Add the parent directory if not the root */
+ if (strcmp(p_cb->p_path, p_cb->p_rootpath))
+ {
+ temp_len = strlen(BTA_FTS_PARENT_FOLDER);
+ memcpy(p_obx->p_start + p_obx->offset,
+ BTA_FTS_PARENT_FOLDER, temp_len);
+ p_obx->bytes_left -= temp_len;
+ p_obx->offset += temp_len;
+ }
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_getdirentry (p_cb->p_path, TRUE, p_dir->p_entry,
+ BTA_FTS_CI_DIRENTRY_EVT, p_cb->app_id);
+
+ /* List is not complete, so don't send the response yet */
+ rsp_code = OBX_RSP_PART_CONTENT;
+ }
+ else /* Add the entry previously retrieved */
+ rsp_code = bta_fts_add_list_entry();
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+ else /* Error occurred */
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ /* Response goes out if complete or error occurred */
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_fts_end_of_list(rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_proc_get_file
+**
+** Description Processes a Get File Operation.
+** If first OBX request, the file is opened, otherwise if it is
+** a continuation the next read is initiated.
+**
+** Parameters p_pkt - Pointer to the OBX Get request
+** name of file to read.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_proc_get_file(char *p_name)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ p_obx->offset = 0;
+
+ /* Allocate an OBX packet */
+ if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ p_cb->peer_mtu)) != NULL)
+ {
+ /* Is this a new request or continuation? */
+ if ((p_cb->obx_oper == FTS_OP_NONE))
+ {
+ /* Validate the name */
+ if (p_name)
+ {
+ if ((p_cb->p_path =
+ (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ /* Build a fully qualified path */
+ if ((strlen(p_cb->p_workdir) + strlen(p_name) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ rsp_code = OBX_RSP_OK;
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+
+ APPL_TRACE_EVENT1("FTS GET FILE: Name [%s]", p_cb->p_path);
+
+ p_cb->obx_oper = FTS_OP_GET_FILE;
+
+ /* Notify the application that a get file has been requested */
+ bta_fts_req_app_access (BTA_FT_OPER_GET, p_cb);
+ }
+ }
+ }
+ }
+ else /* Continue reading from the file */
+ {
+ /* Add the start of the Body Header */
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ rsp_code = OBX_RSP_OK;
+ p_cb->cout_active = TRUE;
+ bta_fs_co_read(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_FTS_CI_READ_EVT, 0, p_cb->app_id);
+ }
+ }
+ if (rsp_code != OBX_RSP_OK)
+ bta_fts_get_file_rsp(rsp_code, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_proc_put_file
+**
+** Description Processes a Put File Operation.
+** Initiates the opening of a file for writing, or continues
+** with a new Obx packet of data (continuation).
+**
+** Parameters p_pkt - Pointer to the OBX Put request
+** name of file to write out.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_proc_put_file(BT_HDR *p_pkt, char *p_name, BOOLEAN final_pkt, UINT8 oper)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FS_CO_STATUS status;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ UINT8 num_hdrs;
+ BOOLEAN is_dir;
+ BOOLEAN endpkt;
+
+ p_obx->final_pkt = final_pkt;
+ p_obx->p_pkt = p_pkt;
+ p_obx->offset = 0; /* Initial offset into OBX data */
+ APPL_TRACE_DEBUG2("bta_fts_proc_put_file len:%d p_pkt->offset:%d", p_pkt->len, p_pkt->offset);
+
+ /* Is this a new request or continuation? */
+ if ((p_cb->obx_oper == FTS_OP_NONE))
+ {
+ /* See if the folder permissions are writable in the current folder */
+ if (((status = bta_fs_co_access(p_cb->p_workdir, BTA_FS_ACC_RDWR,
+ &is_dir, p_cb->app_id)) == BTA_FS_CO_OK) && is_dir)
+ {
+ /* Initialize the start of data and length */
+ if ((p_cb->p_path =
+ (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ /* Build a fully qualified path */
+ if ((strlen(p_cb->p_workdir) + strlen(p_name) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ /* Read the file length if header exists */
+ if (!OBX_ReadLengthHdr(p_pkt, &p_cb->file_length))
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+
+ rsp_code = OBX_RSP_PART_CONTENT; /* Do not send OBX response yet */
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+
+ APPL_TRACE_DEBUG2("FTS PUT FILE: Name [%s], Length = 0x%0x (0 = n/a)",
+ p_cb->p_path, p_cb->file_length);
+
+ p_cb->obx_oper = FTS_OP_PUT_FILE;
+
+ /* Get permission before proceeding */
+ bta_fts_req_app_access(BTA_FT_OPER_PUT, p_cb);
+ }
+ }
+ }
+ else
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ }
+ else /* Continue writing to the open file */
+ {
+ /* Read in start of body if there is a body header */
+ num_hdrs = OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start,
+ &p_obx->bytes_left, &endpkt);
+ if (num_hdrs == 1)
+ {
+ if (p_obx->bytes_left)
+ {
+ rsp_code = OBX_RSP_PART_CONTENT; /* Do not send OBX response yet */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_FTS_CI_WRITE_EVT, 0, p_cb->app_id);
+ }
+ else
+ {
+ rsp_code = OBX_RSP_OK;
+ }
+
+ }
+ else if (oper & FTS_OP_RESUME)
+ {
+ rsp_code = OBX_RSP_OK;
+ }
+ else
+ {
+ bta_fts_clean_getput(p_cb, TRUE);
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ }
+
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_fts_put_file_rsp(rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_mkdir
+**
+** Description make a new directory and sets the new path to this directory
+** if successful.
+**
+** Parameters p_pkt - Pointer to the OBX packet
+**
+** Returns UINT8 - OBX response code
+**
+*******************************************************************************/
+UINT8 bta_fts_mkdir(BT_HDR *p_pkt, tBTA_FT_OPER *p_op)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_FAIL;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ char *p_newpath;
+ char *p_name;
+ BOOLEAN is_dir;
+
+ p_newpath = p_cb->p_path;
+ p_name = p_cb->p_name;
+
+ /* the name of the directory being created */
+ if (p_cb->p_name && p_cb->p_name[0])
+ {
+ /* Make sure the new path is not too big */
+ if ((strlen(p_name) + strlen(p_cb->p_workdir) + 1) <= p_bta_fs_cfg->max_path_len)
+ {
+ /* create a temporary path for creation attempt */
+ sprintf(p_newpath, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+
+ /* If the directory already exists, we're done */
+ if (((status = bta_fs_co_access(p_newpath, BTA_FS_ACC_EXIST,
+ &is_dir, p_cb->app_id)) == BTA_FS_CO_OK) && is_dir)
+ {
+ /* If directory exists, skip mkdir and just issue chdir- Note OBX_RSP_CONTINUE used internally by callee */
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+
+ /* See if the folder permissions are writable in the current folder */
+ else if (((status = bta_fs_co_access(p_cb->p_workdir, BTA_FS_ACC_RDWR,
+ &is_dir, p_cb->app_id)) == BTA_FS_CO_OK))
+ {
+ *p_op = BTA_FT_OPER_MK_DIR;
+ }
+ else if (status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED; /* Read only folder, cannot create a new one */
+ }
+ else
+ APPL_TRACE_WARNING0 ("bta_fts_mkdir: path too long!!!");
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+
+
+ APPL_TRACE_DEBUG2("bta_fts_mkdir: co_status [%d], obx_rsp_code [0x%02x]",
+ status, rsp_code);
+
+ return (rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_chdir
+**
+** Description Changes the current path to the specified directory.
+**
+** Parameters p_pkt - Pointer to the OBX packet
+** backup_flag - if TRUE, path adjusted up one level.
+**
+** Returns UINT8 - OBX response code
+**
+*******************************************************************************/
+UINT8 bta_fts_chdir(BT_HDR *p_pkt, BOOLEAN backup_flag, tBTA_FT_OPER *p_op)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ char *p_path = p_cb->p_path;
+ char *p_name = p_cb->p_name;
+ char *p_workdir = p_cb->p_workdir;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ BOOLEAN is_dir;
+
+ if (!backup_flag)
+ {
+
+ /* If No Name header, or empty name header, set to root path */
+ if (p_name == NULL || (p_name && p_name[0] == '\0'))
+ {
+ BCM_STRNCPY_S(p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+
+ rsp_code = OBX_RSP_OK;
+ APPL_TRACE_DEBUG0("FTS: Setting current path to ROOT");
+ }
+// btla-specific ++
+ #if defined (FTS_REJECT_INVALID_OBEX_SET_PATH_REQ) && (FTS_REJECT_INVALID_OBEX_SET_PATH_REQ == TRUE)
+ /* Reject invalid OBEX set path reqeust - DOS or unix/linux like change directory*/
+ else if(strncmp("/", p_name, 1) == 0 || strncmp("..", p_name, 2) == 0)
+ {
+ APPL_TRACE_ERROR0("FTS: Rejecting invalid chdir request start with / or ..");
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+ #endif
+// btla-specific --
+ /* Make sure the new path is not too big */
+ else if ((strlen(p_name) + strlen(p_workdir) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ /* create a temporary path for creation attempt */
+ sprintf(p_path, "%s%c%s", p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+
+ if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST,
+ &is_dir, p_cb->app_id)) == BTA_FS_CO_OK) && is_dir)
+ {
+ *p_op = BTA_FT_OPER_CHG_DIR;
+ }
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+ }
+ else /* Backing up a directory */
+ {
+ /* Backup unless already at root */
+ if (strcmp(p_workdir, p_cb->p_rootpath))
+ {
+ /* if an empty name header exist(although illegal), goes to root */
+ if (p_name && p_name[0] == '\0')
+ {
+ BCM_STRNCPY_S(p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+
+ APPL_TRACE_DEBUG0("FTS: Setting current path to ROOT");
+ }
+ /* otherwise back up one level */
+ /* Find the last occurrence of separator and replace with '\0' */
+ else if((p_path = strrchr(p_workdir, (int)p_bta_fs_cfg->path_separator)) != NULL)
+ *p_path = '\0';
+ APPL_TRACE_DEBUG1("FTS: SET NEW PATH [%s]", p_cb->p_workdir);
+
+ rsp_code = OBX_RSP_OK;
+ }
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+
+ if (rsp_code == OBX_RSP_OK)
+ bta_fs_co_setdir(p_workdir, p_cb->app_id);
+
+ return (rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_delete
+**
+** Description remove a file or directory
+**
+** Parameters
+** p - Pointer to the name of the object store. It is
+** converted into a fully qualified path before call-out
+** function is called (if not a RAM object).
+**
+** Returns void
+**
+** Obex packet is responded to with:
+** OBX_RSP_OK if successful,
+** OBX_RSP_PRECONDTN_FAILED if a directory and not empty,
+** OBX_RSP_UNAUTHORIZED if read only (access problem),
+** OBX_RSP_INTRNL_SRVR_ERR otherwise.
+**
+*******************************************************************************/
+void bta_fts_delete(tBTA_FTS_OBX_EVENT *p_evt, const char *p_name)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ char *p_path;
+ tBTA_FS_CO_STATUS status;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ BOOLEAN is_dir;
+ tBTA_FT_OPER ft_op = BTA_FT_OPER_DEL_FILE;
+ BOOLEAN rsp_now = TRUE;
+
+ if ((p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 2))) != NULL)
+ {
+ p_path = p_cb->p_path;
+ sprintf(p_path, "%s%c%s", p_cb->p_workdir, p_bta_fs_cfg->path_separator,
+ p_name);
+
+ /* Access the object to see if it exists */
+ status = bta_fs_co_access(p_path, BTA_FS_ACC_RDWR, &is_dir, p_cb->app_id);
+ if (status == BTA_FS_CO_OK)
+ {
+ if (is_dir)
+ ft_op = BTA_FT_OPER_DEL_DIR;
+ rsp_now = FALSE;
+ bta_fts_req_app_access(ft_op, p_cb);
+ }
+ else if (status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+
+ }
+ if(rsp_now)
+ {
+ utl_freebuf((void**)&p_cb->p_path);
+ OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_end_of_list
+**
+** Description Finishes up the end body of the listing, and sends out the
+** OBX response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_end_of_list(UINT8 rsp_code)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 temp_len;
+
+ /* Add the end of folder listing string if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* If listing has completed, add on end string (http) */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ temp_len = strlen(BTA_FTS_FOLDER_LISTING_END);
+ memcpy(&p_obx->p_start[p_obx->offset], BTA_FTS_FOLDER_LISTING_END, temp_len);
+ p_obx->offset += temp_len;
+
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE);
+
+ /* Clean up control block */
+ bta_fts_clean_list(p_cb);
+ }
+ else /* More listing data to be sent */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, FALSE);
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+ }
+ else /* An error occurred */
+ {
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_fts_clean_list(p_cb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_get_file_rsp
+**
+** Description Finishes up the end body of the file get, and sends out the
+** OBX response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_get_file_rsp(UINT8 rsp_code, UINT16 num_read)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTS param;
+ BOOLEAN done = TRUE;
+
+ /* Send the response packet if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ p_obx->offset += num_read;
+
+ /* More to be sent */
+ if (rsp_code == OBX_RSP_CONTINUE)
+ {
+ if (p_obx->bytes_left != num_read)
+ APPL_TRACE_WARNING2("FTS Read: Requested (0x%04x), Read In (0x%04x)",
+ p_obx->bytes_left, num_read);
+ done = FALSE;
+ }
+
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, done);
+
+ /* Notify application with progress */
+ if (num_read)
+ {
+ param.prog.bytes = num_read;
+ param.prog.file_size = p_cb->file_length;
+ p_cb->p_cback(BTA_FTS_PROGRESS_EVT, &param);
+ }
+ }
+ else
+ p_cb->obx_oper = FTS_OP_NONE;
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+
+ /* Final response packet sent out */
+ if (done)
+ bta_fts_clean_getput(p_cb, FALSE);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_put_file_rsp
+**
+** Description Responds to a put request, and closes the file if finished
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_put_file_rsp(UINT8 rsp_code)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTS param;
+
+ /* Finished with input packet */
+ utl_freebuf((void**)&p_obx->p_pkt);
+
+ if (rsp_code == OBX_RSP_OK)
+ {
+ /* Update application if file data was transferred */
+ if (p_obx->bytes_left)
+ {
+ param.prog.bytes = p_obx->bytes_left;
+ param.prog.file_size = p_cb->file_length;
+ p_cb->p_cback(BTA_FTS_PROGRESS_EVT, &param);
+ }
+
+ /* If not end of file put, set the continue response */
+ if (!p_obx->final_pkt)
+ rsp_code = OBX_RSP_CONTINUE;
+ else /* Done - free the allocated memory */
+ bta_fts_clean_getput(p_cb, FALSE);
+ }
+ else
+ p_cb->obx_oper = FTS_OP_NONE;
+
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_add_list_entry
+**
+** Description used by bta_fts_getdirlist to write a list entry to an
+** obex packet (byte array).
+**
+** Returns UINT8 - OBX response code
+** OBX_RSP_PART_CONTENT if not finished yet.
+** OBX_RSP_CONTINUE [packet done]
+** Others send error response out
+**
+*******************************************************************************/
+UINT8 bta_fts_add_list_entry(void)
+{
+ tBTA_FTS_CB *p_cb = &bta_fts_cb;
+ tBTA_FTS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FTS_DIRLIST *p_dir = &p_cb->dir;
+ tBTA_FS_DIRENTRY *p_file = p_dir->p_entry;
+ char *p_buf;
+ UINT16 size;
+ UINT8 rsp_code = OBX_RSP_PART_CONTENT;
+
+ if ((p_buf = (char *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
+ {
+ p_buf[0] = '\0';
+
+ APPL_TRACE_DEBUG2("bta_fts_add_list_entry: attr:0x%02x, name:%s",
+ p_file->mode, p_file->p_name);
+
+ if(p_file->mode & BTA_FS_A_DIR) /* Subdirectory */
+ {
+ /* ignore "." and ".." */
+ if (strcmp(p_file->p_name, ".") && strcmp(p_file->p_name, ".."))
+ {
+ sprintf(p_buf, " <" BTA_FTS_FOLDER_ELEM " "
+ BTA_FTS_NAME_ATTR "=\"%s\"/>" BTA_FTS_XML_EOL,
+ p_file->p_name);
+ }
+ }
+ else /* treat anything else as file */
+ {
+ /* Add the creation time if valid */
+ if (p_file->crtime[0] != '\0')
+ {
+ sprintf(p_buf, " <" BTA_FTS_FILE_ELEM " "
+ BTA_FTS_NAME_ATTR "=\"%s\" "
+ BTA_FTS_SIZE_ATTR "=\"%lu\" "
+ BTA_FTS_USER_PERM_ATTR "=\"R%s\" "
+ BTA_FTS_CREATED_ATTR "=\"%s\"/>" BTA_FTS_XML_EOL,
+ p_file->p_name,
+ p_file->filesize,
+ p_file->mode & BTA_FS_A_RDONLY ? "" : "WD",
+ p_file->crtime);
+ }
+ else
+ {
+ sprintf(p_buf, " <" BTA_FTS_FILE_ELEM " "
+ BTA_FTS_NAME_ATTR "=\"%s\" "
+ BTA_FTS_SIZE_ATTR "=\"%lu\" "
+ BTA_FTS_USER_PERM_ATTR "=\"R%s\"/>" BTA_FTS_XML_EOL,
+ p_file->p_name,
+ p_file->filesize,
+ p_file->mode & BTA_FS_A_RDONLY ? "" : "WD");
+ }
+ }
+
+ /* Make sure the entry fits into the current obx packet */
+ size = strlen(p_buf);
+ if (size <= p_obx->bytes_left)
+ {
+ if (size > 0)
+ {
+ memcpy (&p_obx->p_start[p_obx->offset], p_buf, size);
+ p_obx->offset += size;
+ p_obx->bytes_left -= size;
+ }
+ /* Get the next directory entry */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_getdirentry (p_cb->p_path, FALSE, p_dir->p_entry,
+ BTA_FTS_CI_DIRENTRY_EVT, p_cb->app_id);
+ }
+ else /* entry did not fit in current obx packet; try to add entry in next obx req */
+ rsp_code = OBX_RSP_CONTINUE;
+
+ /* Done with temporary buffer */
+ GKI_freebuf(p_buf);
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ return (rsp_code);
+}
+
+
+/*******************************************************************************
+* Static Functions
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_fts_clean_list
+**
+** Description Cleans up the get directory list memory and control block
+**
+** Returns void
+**
+*******************************************
+************************************/
+void bta_fts_clean_list(tBTA_FTS_CB *p_cb)
+{
+ tBTA_FTS_DIRLIST *p_dir = &p_cb->dir;
+ /* Clean up control block */
+ p_cb->obx_oper = FTS_OP_NONE;
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_dir->p_entry);
+ utl_freebuf((void**)&p_cb->p_path);
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_clean_getput
+**
+** Description Cleans up the get/put resources and control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_clean_getput(tBTA_FTS_CB *p_cb, BOOLEAN is_aborted)
+{
+ tBTA_FS_CO_STATUS status;
+ tBTA_FTS_OBJECT objdata;
+ tBTA_FTS_EVT evt = 0;
+
+ /* Clean up control block */
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Notify the application */
+ objdata.p_name = p_cb->p_path;
+
+ if (is_aborted)
+ objdata.status = BTA_FTS_FAIL;
+ else
+ objdata.status = BTA_FTS_OK;
+
+ if (p_cb->obx_oper == FTS_OP_PUT_FILE)
+ {
+ /* Delete an aborted unfinished push file operation */
+ if (is_aborted && p_cb->suspending == FALSE)
+ {
+ status = bta_fs_co_unlink(p_cb->p_path, p_cb->app_id);
+ APPL_TRACE_WARNING2("FTS: Remove ABORTED Push File Operation [%s], status 0x%02x",
+ p_cb->p_path, status);
+ }
+
+ evt = BTA_FTS_PUT_CMPL_EVT;
+ }
+ else if (p_cb->obx_oper == FTS_OP_GET_FILE)
+ {
+ evt = BTA_FTS_GET_CMPL_EVT;
+ }
+
+ if (evt)
+ {
+ /* Notify application of operation complete */
+ p_cb->p_cback(evt, (tBTA_FTS *)&objdata);
+ }
+ }
+
+ p_cb->suspending = FALSE;
+
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+
+ p_cb->obx_oper = FTS_OP_NONE;
+ p_cb->obx.bytes_left = 0;
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+ p_cb->acc_active = 0;
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_disable_cleanup
+**
+** Description Cleans up the resources and control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_disable_cleanup(tBTA_FTS_CB *p_cb)
+{
+ tBTA_FS_CO_STATUS status;
+
+ /* Stop the OBEX server */
+ OBX_StopServer(p_cb->obx_handle);
+
+ /* Clean up control block */
+ utl_freebuf((void **)&p_cb->obx.p_pkt);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Delete an aborted unfinished push file operation */
+ if (p_cb->obx_oper == FTS_OP_PUT_FILE)
+ {
+ status = bta_fs_co_unlink(p_cb->p_path, p_cb->app_id);
+ APPL_TRACE_WARNING2("FTS: bta_fts_disable_cleanup() ->Remove ABORTED Push File Operation [%s], status 0x%02x",
+ p_cb->p_path, status);
+ }
+ }
+
+ /* Free any used memory buffers */
+ utl_freebuf((void **)&p_cb->dir.p_entry);
+ utl_freebuf((void **)&p_cb->p_name);
+ utl_freebuf((void **)&p_cb->p_path);
+
+ /* Remove the FTP service from the SDP database */
+ SDP_DeleteRecord(p_cb->sdp_handle);
+
+ /* Free the allocated server channel number */
+ BTM_FreeSCN(p_cb->scn);
+
+ GKI_freebuf(p_cb->p_rootpath); /* Free buffer containing root and working paths */
+
+ p_cb->obx_oper = FTS_OP_NONE;
+ p_cb->obx.bytes_left = 0;
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+ p_cb->acc_active = 0;
+
+ if (p_cb->p_cback)
+ {
+ /* Notify the application */
+ p_cb->p_cback(BTA_FTS_DISABLE_EVT, 0);
+ p_cb->p_cback = NULL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_fts_discard_data
+**
+** Description frees the data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fts_discard_data(UINT16 event, tBTA_FTS_DATA *p_data)
+{
+ switch(event)
+ {
+ case BTA_FTS_OBX_CONN_EVT:
+ case BTA_FTS_OBX_DISC_EVT:
+ case BTA_FTS_OBX_ABORT_EVT:
+ case BTA_FTS_OBX_PASSWORD_EVT:
+ case BTA_FTS_OBX_CLOSE_EVT:
+ case BTA_FTS_OBX_PUT_EVT:
+ case BTA_FTS_OBX_GET_EVT:
+ case BTA_FTS_OBX_SETPATH_EVT:
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+ break;
+
+ default:
+ /*Nothing to free*/
+ break;
+ }
+}
+
+#endif /* BTA_FT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
new file mode 100644
index 0000000..ce0c209
--- /dev/null
+++ b/bta/gatt/bta_gattc_act.c
@@ -0,0 +1,1789 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_act.c
+**
+** Description: This file contains the GATT client action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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,
+ &notify.char_id.srvc_id,
+ &notify.char_id.char_id,
+ &notify.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, &notify, handle))
+ {
+ /* if app registered for the notification */
+ if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, &notify))
+ {
+ /* 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, &notify);
+ }
+ /* 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..4a87ddf
--- /dev/null
+++ b/bta/gatt/bta_gattc_api.c
@@ -0,0 +1,922 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_api.c
+**
+** Description: This is the implementation of the API for GATT module
+** of BTA.
+**
+** Copyright (c) 2010-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..7234598
--- /dev/null
+++ b/bta/gatt/bta_gattc_cache.c
@@ -0,0 +1,1584 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_cache.c
+**
+** Description: This file contains the GATT client discovery
+** procedures and cache related functions.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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(&param, 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, &param.s_handle, &param.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, &param);
+
+}
+/*******************************************************************************
+**
+** 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..f5b4f41
--- /dev/null
+++ b/bta/gatt/bta_gattc_ci.c
@@ -0,0 +1,125 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_ci.c
+**
+** Description: This is the implementation file for the GATT
+** call-in functions.
+**
+** Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..4ae7697
--- /dev/null
+++ b/bta/gatt/bta_gattc_int.h
@@ -0,0 +1,452 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_int.h
+**
+** Description: This is the private file for the file transfer
+** client (FTC).
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..5016c46
--- /dev/null
+++ b/bta/gatt/bta_gattc_main.c
@@ -0,0 +1,474 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_main.c
+**
+** Description: This file contains the GATT client main functions
+** and state machine.
+**
+** Copyright (c) 2003-2009, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..227129c
--- /dev/null
+++ b/bta/gatt/bta_gattc_utils.c
@@ -0,0 +1,652 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_utils.c
+**
+** Description: This file contains the GATT client utility
+** function.
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..cb56a32
--- /dev/null
+++ b/bta/gatt/bta_gatts_act.c
@@ -0,0 +1,785 @@
+/*****************************************************************************
+**
+** Name: bta_gatts_act.c
+**
+** Description: This file contains the GATT Server action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+
+#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..77a8f6e
--- /dev/null
+++ b/bta/gatt/bta_gatts_api.c
@@ -0,0 +1,500 @@
+/*****************************************************************************
+**
+** Name: bta_gatts_api.c
+**
+** Description: This is the implementation of the API for GATT server
+** of BTA.
+**
+** Copyright (c) 2010-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..77945f0
--- /dev/null
+++ b/bta/gatt/bta_gatts_int.h
@@ -0,0 +1,233 @@
+/*****************************************************************************
+**
+** Name: bta_gatts_int.h
+**
+** Description: This is the private file for the BTA GATT server.
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..6870016
--- /dev/null
+++ b/bta/gatt/bta_gatts_main.c
@@ -0,0 +1,122 @@
+/*****************************************************************************
+**
+** Name: bta_gatts_main.c
+**
+** Description: This file contains the GATT server main functions
+** and state machine.
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..8f00793
--- /dev/null
+++ b/bta/gatt/bta_gatts_utils.c
@@ -0,0 +1,223 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_utils.c
+**
+** Description: This file contains the GATT client utility
+** function.
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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/hd/bta_hd_act.c b/bta/hd/bta_hd_act.c
new file mode 100644
index 0000000..0e6393b
--- /dev/null
+++ b/bta/hd/bta_hd_act.c
@@ -0,0 +1,646 @@
+/******************************************************************************
+**
+** File Name: bta_hd_act.c
+**
+** Description: This module contains state machine action functions for
+** the HID Device service.
+**
+** Copyright (c) 2002-2009, Broadcom Corp., All Rights Reserved.
+** WIDCOMM Bluetooth Core. Proprietary and confidential.
+**
+******************************************************************************/
+
+#include <string.h>
+#include "data_types.h"
+#include "bt_types.h"
+#include "bt_target.h"
+#include "hidd_api.h"
+#include "bta_hd_int.h"
+#include "bta_hd_api.h"
+#include "l2c_api.h"
+#include "btm_api.h"
+#include "bd.h"
+
+
+
+const UINT8 bta_hd_buf_len[] =
+{
+ BTA_HD_KBD_REPT_SIZE, /* BTA_HD_REPT_ID_SPEC 0: other */
+ BTA_HD_KBD_REPT_SIZE, /* BTA_HD_REPT_ID_KBD 1: regular keyboard */
+ BTA_HD_MOUSE_REPT_SIZE /* BTA_HD_REPT_ID_MOUSE 2: mouse */
+};
+
+typedef struct
+{
+ UINT8 modifier;
+ UINT8 reserved;
+ UINT8 keycode_1;
+ UINT8 keycode_2;
+ UINT8 keycode_3;
+ UINT8 keycode_4;
+ UINT8 keycode_5;
+ UINT8 keycode_6;
+} tBTA_HD_KEY_REPORT;
+
+
+#if (BT_USE_TRACES == TRUE)
+const char * bta_hd_ctrl_str [] =
+{
+ "NOP",
+ "HARD_RESET",
+ "SOFT_RESET",
+ "SUSPEND",
+ "EXIT_SUSPEND",
+ "VCAB_UNPLUG"
+};
+
+const char * bta_hd_rept_id_str [] =
+{
+ "MASK",
+ "OTHER",
+ "INPUT",
+ "OUTPUT",
+ "FEATURE"
+};
+
+const char * bta_hd_evt_str [] =
+{
+ "OPEN",
+ "CLOSE",
+ "RETRYING",
+ "MODE_CHG",
+ "PM_FAILED",
+ "CONTROL",
+ "GET_REPORT",
+ "SET_REPORT",
+ "GET_PROTO",
+ "SET_PROTO",
+ "GET_IDLE",
+ "SET_IDLE",
+ "DATA",
+ "DATC",
+ "L2C_CONG",
+};
+#endif
+
+/*******************************************************************************
+**
+** Function bta_hd_kick_timer
+**
+** Description kick the timer in DM for power management
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hd_kick_timer(tBTA_HD_CB *p_cb)
+{
+ APPL_TRACE_DEBUG0("bta_hd_kick_timer");
+#if (BTM_SSR_INCLUDED == TRUE)
+ if(!p_cb->use_ssr)
+#endif
+ {
+ bta_sys_busy(BTA_ID_HD, p_cb->app_id, p_cb->peer_addr);
+ bta_sys_idle(BTA_ID_HD, p_cb->app_id, p_cb->peer_addr);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_hd_ssr_timer_cback
+**
+** Description Sends disable event to application
+**
+**
+** Returns void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+static void bta_hd_ssr_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+ tBTA_HD_CB *p_cb = (tBTA_HD_CB *)p_tle->param;
+ p_cb->use_ssr = BTA_DmUseSsr(p_cb->peer_addr);
+ APPL_TRACE_DEBUG1("bta_hd_ssr_timer_cback use_ssr:%d", p_cb->use_ssr);
+ bta_sys_idle(BTA_ID_HD, p_cb->app_id, p_cb->peer_addr);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function bta_hd_send_data
+**
+** Description Send data to the connected host
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hd_send_data(tBTA_HD_CB *p_cb, UINT8 rep_type, UINT16 len, UINT8 *p_data)
+{
+ BT_HDR *p_buf;
+ UINT8 *p;
+
+ p_buf = (BT_HDR *) GKI_getbuf( (UINT16)(L2CAP_MIN_OFFSET+len + 1) );
+ if(p_buf)
+ {
+ p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET+1;
+ memcpy( p, p_data, len);
+ p_buf->len = len;
+ p_buf->offset = L2CAP_MIN_OFFSET+1;
+ HID_DevSendData ( TRUE, rep_type, p_buf );
+ if(p_cb)
+ {
+ bta_hd_kick_timer(p_cb);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_flush_data
+**
+** Description Send the queued data to the connected host
+**
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+static BOOLEAN bta_hd_flush_data(tBTA_HD_CB *p_cb)
+{
+ BT_HDR *p_buf;
+ BOOLEAN set_busy = FALSE;
+
+ while((p_buf = (BT_HDR*)GKI_dequeue (&p_cb->out_q)) != NULL)
+ {
+ if(HID_DevSendData ( FALSE, HID_PAR_REP_TYPE_INPUT, p_buf ) == HID_ERR_CONGESTED)
+ {
+ /* can not send it now. put it back to the queue */
+ GKI_enqueue_head(&p_cb->out_q, p_buf);
+ break;
+ }
+
+ /* sent one packet */
+ set_busy = TRUE;
+ }
+
+ if(set_busy)
+ {
+ bta_hd_kick_timer(p_cb);
+ }
+ return GKI_queue_is_empty(&p_cb->out_q);
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_init_con_act
+**
+** Description Initialize the connection to the known host.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_init_con_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data)
+{
+ APPL_TRACE_DEBUG0("bta_hd_init_con_act");
+ if( HID_DevConnect() != HID_SUCCESS )
+ {
+ bta_hd_sm_execute(p_cb, BTA_HD_DISCONNECTED_EVT, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_close_act
+**
+** Description process close API function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_close_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data)
+{
+ APPL_TRACE_DEBUG0("bta_hd_close_act");
+ HID_DevDisconnect();
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_disable_act
+**
+** Description process disable API function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_disable_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data)
+{
+ APPL_TRACE_DEBUG0("bta_hd_disable_act");
+ BTM_SecClrService(BTM_SEC_SERVICE_HID_SEC_CTRL);
+ BTM_SecClrService(BTM_SEC_SERVICE_HID_INTR);
+ if(bta_hd_cb.sdp_handle)
+ {
+ SDP_DeleteRecord(bta_hd_cb.sdp_handle);
+ bta_hd_cb.sdp_handle = 0;
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+ bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
+#endif
+ }
+ HID_DevDeregister();
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_open_act
+**
+** Description received connected event from HIDD. report to user
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_open_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data)
+{
+ BD_ADDR_PTR p_addr = p_data->cback_data.pdata->host_bdaddr;
+#if (BTM_SSR_INCLUDED == TRUE)
+ UINT8 *p;
+#endif
+
+ p_cb->proto = HID_PAR_PROTOCOL_REPORT; /* the default is report mode */
+ bdcpy(p_cb->peer_addr, p_addr);
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_HD ,p_cb->app_id, p_addr);
+#if (BTM_SSR_INCLUDED == TRUE)
+ p_cb->timer.param = (UINT32)p_cb;
+ p_cb->timer.p_cback = (TIMER_CBACK*)&bta_hd_ssr_timer_cback;
+ bta_sys_start_timer(&p_cb->timer, 0, 6000);
+ p_cb->use_ssr = FALSE;
+ if( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+ ((NULL != (p = BTM_ReadRemoteFeatures (p_addr))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) )
+ {
+ /* both local and remote devices support SSR */
+ p_cb->use_ssr = TRUE;
+ }
+#endif
+ p_cb->p_cback(BTA_HD_OPEN_EVT, (tBTA_HD *)p_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_opn_cb_act
+**
+** Description process events from HIDD in open state.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_opn_cb_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data)
+{
+ UINT8 res_code;
+ BOOLEAN *p_cong;
+ tHID_DEV_DSCP_INFO *p_info;
+ tBTA_HD_CBACK_DATA *p_evt = (tBTA_HD_CBACK_DATA *)p_data;
+ BOOLEAN set_busy = TRUE;
+ tBTA_HD_REPORT rpt;
+ UINT8 evt;
+ BT_HDR *p_buf;
+
+ switch(p_evt->event)
+ {
+ case HID_DEV_EVT_CONTROL: /* Host sent HID_CONTROL Data=Control Operation */
+ if(p_evt->data == HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG)
+ {
+ p_cb->p_cback(BTA_HD_UNPLUG_EVT, NULL);
+ set_busy = FALSE;
+ }
+ else if(p_evt->data == HID_PAR_CONTROL_SUSPEND)
+ {
+ bta_sys_idle(BTA_ID_HD, p_cb->app_id, p_cb->peer_addr);
+ set_busy = FALSE;
+ }
+ break;
+
+ case HID_DEV_EVT_GET_REPORT:/*Host sent GET_REPORT Data=Length pdata=structure
+ having details of get-report.*/
+ /* bta_hd_hidd_cback sends SM event only when
+ ((tHID_DEV_GET_REP_DATA *)p_data))->rep_type == HID_PAR_REP_TYPE_FEATURE */
+ p_info = &p_bta_hd_cfg->sdp_info.dscp_info;
+ bta_hd_send_data(p_cb, HID_PAR_REP_TYPE_FEATURE, p_info->dl_len, p_info->dsc_list);
+ break;
+
+ case HID_DEV_EVT_GET_PROTO:/*Host sent GET_PROTOCOL Data=NA*/
+ res_code = p_cb->proto; /* the protocol (Report or Boot) mode from control block */
+ bta_hd_send_data(p_cb, HID_PAR_REP_TYPE_OTHER, 1, &res_code);
+ break;
+
+ case HID_DEV_EVT_SET_PROTO:/*Host sent SET_PROTOCOL Data=1 for Report, 0 for Boot*/
+ if((p_evt->data == HID_PAR_PROTOCOL_REPORT) || (p_evt->data == HID_PAR_PROTOCOL_BOOT_MODE))
+ {
+ p_cb->proto = p_evt->data;
+ res_code = HID_PAR_HANDSHAKE_RSP_SUCCESS;
+ }
+ else
+ res_code = HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ;
+ HID_DevHandShake(res_code);
+ break;
+
+ case HID_DEV_EVT_L2CAP_CONGEST:
+ p_cong = (BOOLEAN *)p_evt->pdata;
+ if(*p_cong == FALSE)
+ {
+ /* L2CAP is uncongested, send out the queued buffers */
+ bta_hd_flush_data(p_cb);
+ set_busy = FALSE;
+ }
+ break;
+
+ case HID_DEV_EVT_DATA:
+ case HID_DEV_EVT_DATC:
+ evt = (p_evt->event == HID_DEV_EVT_DATA) ? BTA_HD_DATA_EVT: BTA_HD_DATC_EVT;
+ if(p_evt->pdata)
+ {
+ if(p_evt->data == HID_PAR_REP_TYPE_OUTPUT)
+ {
+ p_buf = p_evt->pdata->buffer;
+
+ rpt.p_data = (UINT8 *)(p_buf + 1) + p_buf->offset + 1;
+ rpt.len = p_buf->len - 1;
+
+ p_cb->p_cback(evt, (tBTA_HD *)&rpt);
+ }
+
+ GKI_freebuf (p_evt->pdata->buffer);
+ }
+ break;
+ }
+
+ if(set_busy)
+ {
+ bta_hd_kick_timer(p_cb);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_input_act
+**
+** Description received input event from user. send to peer
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_input_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data)
+{
+ tBTA_HD_API_INPUT_SPEC *p_spec = (tBTA_HD_API_INPUT_SPEC *)p_data;
+ tBTA_HD_API_INPUT *p_input = (tBTA_HD_API_INPUT *)p_data;
+ tBTA_HD_KEY_REPORT key_buf = {0};
+ UINT16 len = bta_hd_buf_len[p_input->rid];
+ UINT16 size;
+ BT_HDR *p_buf;
+ UINT8 *p;
+ int temp;
+ BOOLEAN release = FALSE;
+
+ if(p_input->rid == BTA_HD_REPT_ID_SPEC)
+ len = BTA_HD_KBD_REPT_SIZE;
+ size = L2CAP_MIN_OFFSET + sizeof(BT_HDR) + len;
+
+ if ( (p_buf = (BT_HDR *)GKI_getbuf(size)) == NULL )
+ return;
+
+ p_buf->offset = L2CAP_MIN_OFFSET+1;
+ p = (UINT8 *) ((UINT8 *) (p_buf+1))+L2CAP_MIN_OFFSET+1;
+ *p++ = p_input->rid;
+ switch(p_input->rid)
+ {
+ case BTA_HD_REPT_ID_SPEC:
+ p--;
+ memcpy(p, p_spec->seq, p_spec->len);
+ /* use the proper report ID type for the key release */
+ p_input->rid = *p;
+ temp = BTA_HD_KBD_REPT_SIZE - p_spec->len;
+ if(temp > 0)
+ memset(p + p_spec->len, 0, temp);
+ release = p_spec->release;
+ break;
+
+ case BTA_HD_REPT_ID_KBD: /* 1: regular keyboard */
+ key_buf.keycode_1 = p_input->keyCode;
+ key_buf.modifier = p_input->buttons;
+ memcpy(p, (void *)&key_buf, len-1);
+ release = p_input->release;
+ break;
+
+ case BTA_HD_REPT_ID_MOUSE: /* 2: mouse */
+ *p++ = p_input->buttons;
+ *p++ = p_input->keyCode; /* x */
+ *p++ = p_input->keyCode2; /* y */
+ *p++ = p_input->wheel;
+ break;
+
+ default:
+ GKI_freebuf(p_buf);
+ return;
+ }
+ p_buf->len = len;
+
+ GKI_enqueue(&p_cb->out_q, p_buf);
+
+ if(release)
+ {
+ /* key release event */
+ if ( (p_buf = (BT_HDR *)GKI_getbuf(size)) == NULL )
+ return;
+
+ p_buf->offset = L2CAP_MIN_OFFSET+1;
+ p_buf->len = len;
+ p = (UINT8 *) ((UINT8 *) (p_buf+1))+L2CAP_MIN_OFFSET+1;
+ *p++ = p_input->rid;
+ memset(p, 0, p_buf->len-1);
+ GKI_enqueue(&p_cb->out_q, p_buf);
+ }
+ bta_hd_flush_data(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_discntd_act
+**
+** Description received disconnected event from HIDD. report to user
+** The connection was not open yet at this action
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_discntd_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data)
+{
+#if (BTM_SSR_INCLUDED == TRUE)
+ bta_sys_stop_timer(&p_cb->timer);
+#endif
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_HD ,p_cb->app_id, p_cb->peer_addr);
+ p_cb->p_cback(BTA_HD_CLOSE_EVT, (tBTA_HD *)p_cb->peer_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_discnt_act
+**
+** Description received disconnected event from HIDD. report to user
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_discnt_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data)
+{
+ BT_HDR *p_buf;
+
+#if (BTM_SSR_INCLUDED == TRUE)
+ bta_sys_stop_timer(&p_cb->timer);
+#endif
+
+ /* clean out queue */
+ while((p_buf = (BT_HDR*)GKI_dequeue (&p_cb->out_q)) != NULL)
+ GKI_freebuf(p_buf);
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_HD ,p_cb->app_id, p_cb->peer_addr);
+ p_cb->p_cback(BTA_HD_CLOSE_EVT, (tBTA_HD *)p_cb->peer_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_hidd_cback
+**
+** Description This is the HIDD callback function to process events from HIDD.
+** just post a message to BTA_HD
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_hidd_cback(UINT8 event, UINT32 data, tHID_DEV_CBACK_DATA *pdata)
+{
+ tBTA_HD_CBACK_DATA *p_buf;
+ tHID_DEV_GET_REP_DATA *pget_rep;
+ UINT16 sm_evt = BTA_HD_INVALID_EVT;
+ UINT8 res_code;
+
+#if (BT_USE_TRACES == TRUE)
+ APPL_TRACE_EVENT3("HID event=0x%x(%s), data: %d", event, bta_hd_evt_str[event], data);
+#endif
+
+ switch( event )
+ {
+ case HID_DEV_EVT_OPEN: /*Connected to host Data = 1 if Virtual Cable
+ with Interrupt and Control
+ Channels in OPEN state. pdata = Host BD-Addr.*/
+ sm_evt = BTA_HD_CONNECTED_EVT;
+ break;
+
+ case HID_DEV_EVT_CLOSE: /*Connection with host is closed. Data=Reason Code. */
+ sm_evt = BTA_HD_DISCONNECTED_EVT;
+ break;
+
+ /*case HID_DEV_EVT_RETRYING: Data=Retrial number
+ Lost connection is being re-connected.
+ MSKB_TRACE_0("HID_DEV_EVT_RETRYING");
+ break; */
+
+ /*case HID_DEV_EVT_MODE_CHG: Device changed power mode. Data=new power mode
+ APPL_TRACE_DEBUG1("Mode change - %d", data);
+ break; */
+
+ /*case HID_DEV_EVT_PM_FAILED: Host sent SET_IDLE Data=Idle Rate
+ MSKB_TRACE_0("PM - Failed");
+ break; */
+
+ case HID_DEV_EVT_CONTROL: /* Host sent HID_CONTROL Data=Control Operation */
+#if (BT_USE_TRACES == TRUE)
+ APPL_TRACE_DEBUG2("EVT_CONTROL:%d(%s)",data, bta_hd_ctrl_str[data]);
+#endif
+ switch(data)
+ {
+ case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG:
+ case HID_PAR_CONTROL_SUSPEND:
+ case HID_PAR_CONTROL_EXIT_SUSPEND:
+ sm_evt = BTA_HD_CBACK_EVT ;
+ HID_DevHandShake(HID_PAR_HANDSHAKE_RSP_SUCCESS);
+ break;
+ default:
+ HID_DevHandShake(HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ);
+ }
+ break;
+
+ case HID_DEV_EVT_GET_REPORT:/*Host sent GET_REPORT Data=Length pdata=structure
+ having details of get-report.*/
+ pget_rep = (tHID_DEV_GET_REP_DATA *) pdata;
+ APPL_TRACE_DEBUG3("RepType:%d(%s), id:%d",pget_rep->rep_type,
+ bta_hd_rept_id_str[pget_rep->rep_type], pget_rep->rep_id);
+
+ if(pget_rep->rep_type == HID_PAR_REP_TYPE_FEATURE)
+ {
+ sm_evt = BTA_HD_CBACK_EVT ;
+ }
+ else
+ {
+ HID_DevHandShake(HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ);
+ }
+ break;
+ case HID_DEV_EVT_SET_REPORT:/*Host sent SET_REPORT Data=Length pdata=details.*/
+ HID_DevHandShake(HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ);
+ APPL_TRACE_EVENT0("HID_DEV_EVT_SET_REPORT");
+ GKI_freebuf (pdata->buffer);
+ break;
+ case HID_DEV_EVT_GET_PROTO:/*Host sent GET_PROTOCOL Data=NA*/
+ sm_evt = BTA_HD_CBACK_EVT ;
+ break;
+ case HID_DEV_EVT_SET_PROTO:/*Host sent SET_PROTOCOL Data=1 for Report, 0 for Boot*/
+ sm_evt = BTA_HD_CBACK_EVT ;
+ break;
+ case HID_DEV_EVT_GET_IDLE:/* Host sent GET_IDLE Data=NA */
+ /* only support infinite idle rate (= 0) */
+ res_code = 0;
+ bta_hd_send_data(NULL, HID_PAR_REP_TYPE_OTHER, 1, &res_code);
+ break;
+ case HID_DEV_EVT_SET_IDLE: /* Host sent SET_IDLE Data=Idle Rate */
+ res_code = HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM;
+ if( data == 0 ) /* only support infinite idle rate (= 0) */
+ res_code = HID_PAR_HANDSHAKE_RSP_SUCCESS;
+ HID_DevHandShake(res_code);
+ break;
+ case HID_DEV_EVT_L2CAP_CONGEST:
+ sm_evt = BTA_HD_CBACK_EVT ;
+ break;
+ case HID_DEV_EVT_DATA:
+ case HID_DEV_EVT_DATC:
+ APPL_TRACE_EVENT1("HID_DEV_EVT_DATC/DATC event = %s", bta_hd_evt_str[event]);
+ sm_evt = BTA_HD_CBACK_EVT ;
+ break;
+ }
+
+ if ((sm_evt != BTA_HD_INVALID_EVT) &&
+ (p_buf = (tBTA_HD_CBACK_DATA *) GKI_getbuf(
+ (UINT16)(sizeof(tBTA_HD_CBACK_DATA)+sizeof(tHID_DEV_CBACK_DATA)))) != NULL)
+ {
+ p_buf->hdr.event = sm_evt;
+ p_buf->event = event;
+ p_buf->data = data;
+ if(pdata)
+ {
+ p_buf->pdata = (tHID_DEV_CBACK_DATA *)(p_buf + 1);
+ memcpy(p_buf->pdata, pdata, sizeof(tHID_DEV_CBACK_DATA));
+ }
+ else
+ {
+ p_buf->pdata = NULL;
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+
+
+}
+
diff --git a/bta/hd/bta_hd_api.c b/bta/hd/bta_hd_api.c
new file mode 100644
index 0000000..6709c1d
--- /dev/null
+++ b/bta/hd/bta_hd_api.c
@@ -0,0 +1,236 @@
+/******************************************************************************
+**
+** File Name: bta_hd_api.c
+**
+** Description: This is the API functions for the HID Device
+** service.
+**
+** Copyright (c) 2002-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+******************************************************************************/
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_hd_api.h"
+#include "bta_hd_int.h"
+#include "gki.h"
+#include <string.h>
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_hd_reg =
+{
+ bta_hd_hdl_event,
+ BTA_HdDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_HdEnable
+**
+** Description Enable the HID Device service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_HD_ENABLE_EVT. This function must
+** be called before other function in the HD API are
+** called.
+**
+** If all bytes of the specified bd_addr are 0xff, the
+** peer address is considered as unknown. The HID device listens
+** for incoming connection request.
+** Otherwise, The HID device initiates a connection toward the
+** specified bd_addr when BTA_HdOpen() is called.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HdEnable(BD_ADDR bd_addr, tBTA_SEC sec_mask, const char *p_service_name,
+ tBTA_HD_CBACK *p_cback, UINT8 app_id)
+{
+ tBTA_HD_API_ENABLE *p_buf;
+
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_HD, &bta_hd_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_HD_API_ENABLE *) GKI_getbuf(sizeof(tBTA_HD_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HD_API_ENABLE_EVT;
+ p_buf->app_id = app_id;
+ if(p_service_name)
+ {
+ BCM_STRNCPY_S(p_buf->service_name, sizeof(p_buf->service_name), p_service_name, BTA_SERVICE_NAME_LEN);
+ p_buf->service_name[BTA_SERVICE_NAME_LEN] = 0;
+ }
+ else
+ {
+ p_buf->service_name[0] = 0;
+ }
+ p_buf->p_cback = p_cback;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ p_buf->sec_mask = sec_mask;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HdDisable
+**
+** Description Disable the HID Device service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HdDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_HD);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_HD_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HdOpen
+**
+** Description Opens an HID Device connection to a peer device.
+** When connection is open, callback function is called
+** with a BTA_HD_OPEN_EVT.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HdOpen(tBTA_SEC sec_mask)
+{
+ tBTA_HD_API_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_HD_API_OPEN *) GKI_getbuf(sizeof(tBTA_HD_API_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HD_API_OPEN_EVT;
+ p_buf->sec_mask = sec_mask;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HdClose
+**
+** Description Close the current connection a peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HdClose(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_HD_API_CLOSE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_HdSendRegularKey
+**
+** Description Send a key report to the connected host.
+** If auto_release is TRUE, assume the keyboard report must be
+** a key press. An associated key release report is also sent.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HdSendRegularKey (UINT8 modifier, UINT8 key_code, BOOLEAN auto_release)
+{
+ tBTA_HD_API_INPUT *p_buf;
+
+ if ((p_buf = (tBTA_HD_API_INPUT *) GKI_getbuf(sizeof(tBTA_HD_API_INPUT))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HD_API_INPUT_EVT;
+ p_buf->rid = BTA_HD_REPT_ID_KBD;
+ p_buf->keyCode = key_code;
+ p_buf->buttons = modifier;
+ p_buf->release = auto_release;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HdSendSpecialKey
+**
+** Description Send a special key report to the connected host.
+** The report is sent as a keyboard report.
+** If auto_release is TRUE, assume the keyboard report must be
+** a key press. An associated key release report is also sent.
+** If key_len is less than BTA_HD_KBD_REPT_SIZE, the key_seq
+** is padded with 0 until BTA_HD_KBD_REPT_SIZE.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HdSendSpecialKey (UINT8 key_len, UINT8 * key_seq, BOOLEAN auto_release)
+{
+ tBTA_HD_API_INPUT_SPEC *p_buf;
+
+ if ((p_buf = (tBTA_HD_API_INPUT_SPEC *) GKI_getbuf(
+ (UINT16)(sizeof(tBTA_HD_API_INPUT_SPEC)+key_len))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HD_API_INPUT_EVT;
+ p_buf->rid = BTA_HD_REPT_ID_SPEC;
+ p_buf->len = key_len;
+ p_buf->seq = (UINT8 *)(p_buf+1);
+ p_buf->release = auto_release;
+ memcpy(p_buf->seq, key_seq, key_len);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_HdSendMouseReport
+**
+** Description Send a mouse report to the connected host
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_HdSendMouseReport (UINT8 is_left, UINT8 is_right, UINT8 is_middle,
+ INT8 delta_x, INT8 delta_y, INT8 delta_wheel)
+{
+ tBTA_HD_API_INPUT *p_buf;
+
+ if ((p_buf = (tBTA_HD_API_INPUT *) GKI_getbuf(sizeof(tBTA_HD_API_INPUT))) != NULL)
+ {
+ p_buf->hdr.event = BTA_HD_API_INPUT_EVT;
+ p_buf->rid = BTA_HD_REPT_ID_MOUSE;
+ p_buf->keyCode = (UINT8)delta_x;
+ p_buf->keyCode2 = (UINT8)delta_y;
+ p_buf->buttons = (is_left ? 0x01 : 0x00) |
+ (is_right ? 0x02 : 0x00) |
+ (is_middle ? 0x04 : 0x00);
+ p_buf->wheel = (UINT8)delta_wheel;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
+
diff --git a/bta/hd/bta_hd_cfg.c b/bta/hd/bta_hd_cfg.c
new file mode 100644
index 0000000..4256ba2
--- /dev/null
+++ b/bta/hd/bta_hd_cfg.c
@@ -0,0 +1,151 @@
+/*****************************************************************************
+**
+** Name: bta_hd_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for HID Device
+**
+** Copyright (c) 2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "gki.h"
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_hd_api.h"
+
+const UINT8 bta_hd_cfg_report[] =
+{
+ 0x05, 0x01, /* Usage page Desktop 01 */
+ 0x09, 0x06, /* Usage Keyboard 06 */
+ 0xa1, 0x01, /* Collection appliction */
+ 0x05, 0x07, /* Usage page Keyboard */
+ 0x85, BTA_HD_REPT_ID_KBD, /* Report ID 1 */
+ 0x19, 0xe0, /* Usage minimum e0 (leftControl) */
+ 0x29, 0xe7, /* Usage maximum e7 (right gui) */
+ 0x15, 0x00, /* Logical mimumum 0 */
+ 0x25, 0x01, /* Logical Maximum 1 */
+ 0x75, 0x01, /* Report size 1 */
+ 0x95, 0x08, /* Report count 8 */
+ 0x81, 0x02, /* Input Variable Abs */
+ 0x95, 0x01, /* Report count 1 */
+ 0x75, 0x08, /* Report size 8 */
+ 0x81, 0x01, /* Iput constant variable */
+ 0x95, 0x05, /* report count 5 */
+ 0x75, 0x01, /* Report size 1 */
+ 0x05, 0x08, /* LED page */
+ 0x19, 0x01, /* Usage minimum 1 Num lock */
+ 0x29, 0x05, /* Usage maximum 5 Kana */
+ 0x91, 0x02, /* Output Data, Variable, Absolute */
+ 0x95, 0x01, /* Report Count 1 */
+ 0x75, 0x03, /* Report Size 3 */
+ 0x91, 0x01, /* Output constant, Absolute */
+ 0x95, 0x06, /* Report Count 6 */
+ 0x75, 0x08, /* Report size 8 */
+ 0x15, 0x00, /* Logical mimumum 0 */
+ 0x26, 0xa4, 0x00, /* Logical Maximum 00a4 */
+ 0x05, 0x07, /* Usage page Keyboard */
+ 0x19, 0x00, /* Usage minimum 0 */
+ 0x29, 0xa4, /* Usage maximum a4 */
+ 0x81, 0x00, /* Input data array absolute */
+ 0xc0,
+
+ 0x05, 0x01, /* Usage page Desktop 01 */
+ 0x09, 0x02, /* Usage 2 Mouse */
+ 0xa1, 0x01, /* Collection appliction */
+ 0x09, 0x01, /* Usage 1 pointer */
+ 0xa1, 0x00, /* Collection physical */
+ 0x85, BTA_HD_REPT_ID_MOUSE, /* report id 2 */
+ 0x05, 0x09, /* Usage page button */
+ 0x19, 0x01, /* Usage minimum 1 */
+ 0x29, 0x03, /* Usage maximum 3 */
+ 0x15, 0x00, /* Logical mimumum 0 */
+ 0x25, 0x01, /* Logical Maximum 1 */
+ 0x95, 0x03, /* Report Count 3 */
+ 0x75, 0x01, /* Report size 1 */
+ 0x81, 0x02, /* Input Variable Abs */
+ 0x95, 0x01, /* Report Count 1 */
+ 0x75, 0x05, /* Report size 5 */
+ 0x81, 0x03, /* Input const var Abs */
+
+ 0x05, 0x01, /* Usage page Desktop 01 */
+ 0x09, 0x30, /* Usage X */
+ 0x09, 0x31, /* Usage Y */
+ 0x09, 0x38, /* Usage Wheel */
+ 0x15, 0x81, /* Logical mimumum -127 */
+ 0x25, 0x7f, /* Logical Maximum 127 */
+ 0x75, 0x08, /* Report size 8 */
+ 0x95, 0x03, /* Report Count 3 */
+ 0x81, 0x06, /* Input Variable relative */
+ 0xc0,
+ 0xc0,
+
+ 0x05, 0x0c, /* Usage page (consumer page) */
+ 0x09, 0x01, /* Usage Consumer control */
+ 0xa1, 0x01, /* Collection appliction */
+ 0x85, BTA_HD_REPT_ID_CONSUMER, /* Report ID 3 */
+ 0x75, 0x10, /* report size 16 */
+ 0x95, 0x02, /* report count 2 */
+ 0x15, 0x01, /* Logical mimumum 1 */
+ 0x26, 0x8c, 0x02, /* Logical Maximum 028c */
+ 0x19, 0x01, /* Usage minimum 1 */
+ 0x2a, 0x8c, 0x02, /* Usage maximum 028c */
+ 0x81, 0x60, /* Input Data array absolute No preferred, Null state */
+ 0xc0,
+};
+
+
+const tBTA_HD_CFG bta_hd_cfg =
+{
+ {
+ {
+ 0, /* qos_flags */
+ 1, /* service type */
+ 800, /* token rate (bytes/second) */
+ 8, /* token_bucket_size (bytes) */
+ 0, /* peak_bandwidth (bytes/second) */
+ 0xffffffff, /* latency(microseconds) */
+ 0xffffffff /* delay_variation(microseconds) */
+ }, /* ctrl_ch */
+ {
+ 0, /* qos_flags */
+ 1, /* service type */
+ 300, /* token rate (bytes/second) */
+ 4, /* token_bucket_size (bytes) */
+ 300, /* peak_bandwidth (bytes/second) */
+ 10000, /* latency(microseconds) */
+ 10000 /* delay_variation(microseconds) */
+ }, /* int_ch */
+ {
+ 0, /* qos_flags */
+ 2, /* service type */
+ 400, /* token rate (bytes/second) */
+ 8, /* token_bucket_size (bytes) */
+ 800, /* peak_bandwidth (bytes/second) */
+ 10000, /* latency(microseconds) */
+ 10000 /* delay_variation(microseconds) */
+ } /* hci */
+ }, /* qos */
+ {
+ "BTA HID Device", /* Service name */
+ "Remote Control", /* Service Description */
+ "Broadcom Corp", /* Provider Name.*/
+ 0x0100, /* HID device release number */
+ 0x0111, /* HID Parser Version.*/
+ HID_SSR_PARAM_INVALID, /* SSR max latency */
+ HID_SSR_PARAM_INVALID, /* SSR min timeout */
+ BTM_COD_MINOR_COMBO,/*Device Subclass.*/
+ 0, /* Country Code. (0 for not localized) */
+ 0, /* Supervisory Timeout */
+ {
+ sizeof(bta_hd_cfg_report), /* size of report descriptor */
+ (UINT8 *)bta_hd_cfg_report,/* config report descriptor */
+ }, /* dscp_info */
+ 0 /* p_sdp_layer_rec */
+ }, /* sdp info */
+ 1 /* use QoS */
+};
+
+tBTA_HD_CFG *p_bta_hd_cfg = (tBTA_HD_CFG *) &bta_hd_cfg;
+
diff --git a/bta/hd/bta_hd_int.h b/bta/hd/bta_hd_int.h
new file mode 100644
index 0000000..4ea5365
--- /dev/null
+++ b/bta/hd/bta_hd_int.h
@@ -0,0 +1,166 @@
+/******************************************************************************
+**
+** File Name: bta_hd_int.h
+**
+** Description: This is the internal header file for the HID Device service.
+**
+** Copyright (c) 2002-2009, Broadcom Corp., All Rights Reserved.
+** WIDCOMM Bluetooth Core. Proprietary and confidential.
+**
+******************************************************************************/
+
+#ifndef BTA_HD_INT_H
+#define BTA_HD_INT_H
+
+#include "bt_types.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_hd_api.h"
+
+
+/*****************************************************************************/
+/* C O N S T A N T S */
+/*****************************************************************************/
+
+#define BTA_HD_KEYBOARD_REPORT_SIZE 0x3F
+#define BTA_HD_MOUSE_REPORT_SIZE 0x32
+
+/* BTA_HD State machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_HD_API_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HD),
+ BTA_HD_API_CLOSE_EVT,
+ BTA_HD_API_DISABLE_EVT,
+ BTA_HD_API_INPUT_EVT,
+ BTA_HD_CBACK_EVT,
+ BTA_HD_CONNECTED_EVT,
+ BTA_HD_DISCONNECTED_EVT,
+
+ /* these events are handled outside of the state machine */
+ BTA_HD_API_ENABLE_EVT
+};
+#define BTA_HD_INVALID_EVT (BTA_HD_API_ENABLE_EVT + 1)
+
+/*****************************************************************************
+** Data types
+*****************************************************************************/
+
+/* data type for BTA_HD_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char service_name[BTA_SERVICE_NAME_LEN+1];
+ tBTA_HD_CBACK *p_cback;
+ BD_ADDR bd_addr;
+ tBTA_SEC sec_mask;
+ UINT8 app_id;
+} tBTA_HD_API_ENABLE;
+
+/* data type for BTA_HD_API_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_SEC sec_mask;
+} tBTA_HD_API_OPEN;
+
+
+/* data type for BTA_HD_API_INPUT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HD_REPT_ID rid;
+ UINT8 keyCode; /* if BTA_HD_REPT_ID_MOUSE, X */
+ UINT8 keyCode2; /* if BTA_HD_REPT_ID_MOUSE, Y */
+ UINT8 wheel; /* BTA_HD_REPT_ID_MOUSE only */
+ UINT8 buttons; /* BTA_HD_REPT_ID_MOUSE & BTA_HD_REPT_ID_KBD (modifier) only */
+ BOOLEAN release; /* If TRUE, HD sends release key. not used by mouse report */
+} tBTA_HD_API_INPUT;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_HD_REPT_ID rid;
+ UINT8 len;
+ UINT8 *seq;
+ BOOLEAN release; /* If TRUE, HD sends release key. */
+} tBTA_HD_API_INPUT_SPEC;
+
+/* data type for BTA_HD_CBACK_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 event;
+ UINT32 data;
+ tHID_DEV_CBACK_DATA *pdata;
+} tBTA_HD_CBACK_DATA;
+
+/* union of all event datatypes */
+typedef union
+{
+ tBTA_HD_API_ENABLE api_enable;
+ tBTA_HD_API_OPEN api_open;
+ tBTA_HD_API_INPUT api_input;
+ tBTA_HD_API_INPUT_SPEC api_spec;
+ tBTA_HD_CBACK_DATA cback_data;
+} tBTA_HD_DATA;
+
+
+/* type for HD control block */
+typedef struct
+{
+ BD_ADDR peer_addr; /* peer BD address */
+ UINT32 sdp_handle; /* SDP record handle */
+ tBTA_HD_CBACK *p_cback; /* application callback function */
+ BUFFER_Q out_q; /* Queue for reports */
+ tBTA_SEC sec_mask; /* security mask */
+ UINT8 state; /* state machine state */
+ UINT8 proto; /* protocol (boot or report) */
+ UINT8 app_id;
+#if (BTM_SSR_INCLUDED == TRUE)
+ BOOLEAN use_ssr; /* TRUE, if SSR is supported on this link */
+ TIMER_LIST_ENT timer; /* delay timer to check for SSR */
+#endif
+} tBTA_HD_CB;
+
+/*****************************************************************************/
+/* P U B L I C D A T A */
+/*****************************************************************************/
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* control block declaration */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_HD_CB bta_hd_cb;
+#else
+extern tBTA_HD_CB *bta_hd_cb_ptr;
+#define bta_hd_cb (*bta_hd_cb_ptr)
+#endif
+
+/* config struct */
+extern tBTA_HD_CFG *p_bta_hd_cfg;
+
+/* rc id config struct */
+extern UINT16 *p_bta_hd_rc_id;
+
+/*****************************************************************************/
+/* F U N C T I O N P R O T O T Y P E S */
+/*****************************************************************************/
+
+/* from bta_hd_main.c */
+extern BOOLEAN bta_hd_hdl_event(BT_HDR *p_msg);
+extern void bta_hd_sm_execute(tBTA_HD_CB *p_cb, UINT16 event, tBTA_HD_DATA *p_data);
+/* from bta_hd_act.c */
+extern void bta_hd_init_con_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+extern void bta_hd_close_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+extern void bta_hd_disable_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+extern void bta_hd_open_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+extern void bta_hd_opn_cb_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+extern void bta_hd_input_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+extern void bta_hd_discntd_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+extern void bta_hd_discnt_act(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+extern void bta_hd_hidd_cback(UINT8 event, UINT32 data, tHID_DEV_CBACK_DATA *pdata);
+#endif /* BTA_HD_INT_H */
+
diff --git a/bta/hd/bta_hd_main.c b/bta/hd/bta_hd_main.c
new file mode 100644
index 0000000..ee3efae
--- /dev/null
+++ b/bta/hd/bta_hd_main.c
@@ -0,0 +1,242 @@
+/******************************************************************************
+**
+** File Name: bta_hd_main.c
+**
+** Description: This is the state machine definition for the HID Device
+** service.
+**
+** Copyright (c) 2002-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+******************************************************************************/
+
+#include <string.h>
+#include "bt_target.h"
+#include "data_types.h"
+#include "bt_types.h"
+#include "hidd_api.h"
+#include "bta_hd_api.h"
+#include "bta_hd_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+
+/* state machine states */
+enum
+{
+ BTA_HD_IDLE_ST,
+ BTA_HD_LISTEN_ST,
+ BTA_HD_OPEN_ST
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_HD_INIT_CON_ACT,
+ BTA_HD_CLOSE_ACT,
+ BTA_HD_DISABLE_ACT,
+ BTA_HD_OPEN_ACT,
+ BTA_HD_OPN_CB_ACT,
+ BTA_HD_INPUT_ACT,
+ BTA_HD_DISCNTD_ACT,
+ BTA_HD_DISCNT_ACT,
+ BTA_HD_NUM_ACTIONS
+};
+
+#define BTA_HD_IGNORE BTA_HD_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tBTA_HD_ACTION)(tBTA_HD_CB *p_cb, tBTA_HD_DATA *p_data);
+
+/* action functions */
+const tBTA_HD_ACTION bta_hd_action[] =
+{
+ bta_hd_init_con_act,
+ bta_hd_close_act,
+ bta_hd_disable_act,
+ bta_hd_open_act,
+ bta_hd_opn_cb_act,
+ bta_hd_input_act,
+ bta_hd_discntd_act,
+ bta_hd_discnt_act
+};
+
+/* state table information */
+#define BTA_HD_NUM_ACTS 1 /* number of actions */
+#define BTA_HD_ACTION 0 /* position of action */
+#define BTA_HD_NEXT_STATE 1 /* position of next state */
+#define BTA_HD_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for listen state */
+const UINT8 bta_hd_st_listen[][BTA_HD_NUM_COLS] =
+{
+/* API_OPEN */ {BTA_HD_INIT_CON_ACT, BTA_HD_LISTEN_ST},
+/* API_CLOSE */ {BTA_HD_CLOSE_ACT, BTA_HD_LISTEN_ST},
+/* API_DISABLE */ {BTA_HD_DISABLE_ACT, BTA_HD_IDLE_ST},
+/* API_INPUT */ {BTA_HD_IGNORE, BTA_HD_LISTEN_ST},
+/* CBACK */ {BTA_HD_IGNORE, BTA_HD_LISTEN_ST},
+/* CONNECTED */ {BTA_HD_OPEN_ACT, BTA_HD_OPEN_ST},
+/* DISCONNECT */ {BTA_HD_DISCNTD_ACT, BTA_HD_LISTEN_ST}
+};
+
+/* state table for open state */
+const UINT8 bta_hd_st_open[][BTA_HD_NUM_COLS] =
+{
+/* API_OPEN */ {BTA_HD_IGNORE, BTA_HD_OPEN_ST},
+/* API_CLOSE */ {BTA_HD_CLOSE_ACT, BTA_HD_OPEN_ST},
+/* API_DISABLE */ {BTA_HD_DISABLE_ACT, BTA_HD_IDLE_ST},
+/* API_INPUT */ {BTA_HD_INPUT_ACT, BTA_HD_OPEN_ST},
+/* CBACK */ {BTA_HD_OPN_CB_ACT, BTA_HD_OPEN_ST},
+/* CONNECTED */ {BTA_HD_IGNORE, BTA_HD_OPEN_ST},
+/* DISCONNECT */ {BTA_HD_DISCNT_ACT, BTA_HD_LISTEN_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_HD_ST_TBL)[BTA_HD_NUM_COLS];
+
+/* state table */
+const tBTA_HD_ST_TBL bta_hd_st_tbl[] =
+{
+ bta_hd_st_listen,
+ bta_hd_st_open
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* HD control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_HD_CB bta_hd_cb;
+#endif
+
+
+/*******************************************************************************
+**
+** Function bta_hd_api_enable
+**
+** Description Handle an API enable event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_hd_api_enable(tBTA_HD_DATA *p_data)
+{
+ tHID_DEV_SDP_INFO sdp_info;
+ tHID_DEV_REG_INFO reg_info;
+ tBTA_SEC sec_mask = p_data->api_enable.sec_mask;
+ tBTA_HD_STATUS status = BTA_HD_FAIL;
+
+ /* initialize control block */
+ memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
+ GKI_init_q (&bta_hd_cb.out_q);
+
+ /* store parameters */
+ bta_hd_cb.p_cback = p_data->api_enable.p_cback;
+
+ /* register HID Device to HIDD */
+ reg_info.app_cback = bta_hd_hidd_cback;
+ bdcpy(reg_info.host_addr, p_data->api_enable.bd_addr);
+ if(p_bta_hd_cfg->use_qos)
+ reg_info.qos_info = &p_bta_hd_cfg->qos;
+ else
+ reg_info.qos_info = NULL;
+
+
+ if(HID_DevRegister(&reg_info) == HID_SUCCESS)
+ {
+ HID_DevSetSecurityLevel("BT HID Combo Mouse/Keyboard", sec_mask);
+
+ /* register HID Device to SDP */
+ memcpy(&sdp_info, &p_bta_hd_cfg->sdp_info, sizeof(tHID_DEV_SDP_INFO));
+ if(p_data->api_enable.service_name[0])
+ {
+ BCM_STRNCPY_S(sdp_info.svc_name, sizeof(sdp_info.svc_name), p_data->api_enable.service_name,
+// btla-specific ++
+ sizeof(sdp_info.svc_name));
+// btla-specific --
+ }
+ bta_hd_cb.sdp_handle = HID_DevSetSDPRecord(&sdp_info);
+ }
+
+ if(bta_hd_cb.sdp_handle>0)
+ {
+ status = BTA_HD_SUCCESS;
+ bta_hd_cb.state = BTA_HD_LISTEN_ST;
+ bta_sys_add_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
+ }
+
+ /* call callback with enable event */
+ (*bta_hd_cb.p_cback)(BTA_HD_ENABLE_EVT, (tBTA_HD *)&status);
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_sm_execute
+**
+** Description State machine event handling function for HD
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_hd_sm_execute(tBTA_HD_CB *p_cb, UINT16 event, tBTA_HD_DATA *p_data)
+{
+ tBTA_HD_ST_TBL state_table;
+ UINT8 action;
+
+ if(p_cb->state == BTA_HD_IDLE_ST)
+ {
+ APPL_TRACE_EVENT1("HD event=0x%x received in IDLE", event);
+ return;
+ }
+
+ /* look up the state table for the current state */
+ state_table = bta_hd_st_tbl[p_cb->state-1];
+
+ event &= 0x00FF;
+
+ APPL_TRACE_EVENT3("HD event=0x%x state=%d, next: %d",
+ event, p_cb->state, state_table[event][BTA_HD_NEXT_STATE]);
+ /* set next state */
+ p_cb->state = state_table[event][BTA_HD_NEXT_STATE];
+ action = state_table[event][BTA_HD_ACTION];
+
+ /* execute action functions */
+ if (action != BTA_HD_IGNORE)
+ {
+ (*bta_hd_action[action])(p_cb, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_hd_hdl_event
+**
+** Description HID Device main event handling function.
+**
+**
+** Returns BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN bta_hd_hdl_event(BT_HDR *p_msg)
+{
+ switch (p_msg->event)
+ {
+ /* handle enable event */
+ case BTA_HD_API_ENABLE_EVT:
+ bta_hd_api_enable((tBTA_HD_DATA *) p_msg);
+ break;
+
+ /* all others run through state machine */
+ default:
+ bta_hd_sm_execute(&bta_hd_cb, p_msg->event, (tBTA_HD_DATA *) p_msg);
+ break;
+ }
+ return TRUE;
+}
+
diff --git a/bta/hh/bta_hh_act.c b/bta/hh/bta_hh_act.c
new file mode 100644
index 0000000..483e79c
--- /dev/null
+++ b/bta/hh/bta_hh_act.c
@@ -0,0 +1,1160 @@
+/*****************************************************************************
+**
+** Name: bta_hh_act.c
+**
+** Description: This file contains the HID host action
+** functions.
+**
+** Copyright (c) 2005-2011, Broadcom Corp, All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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;
+ tHID_STATUS status = HID_ERR_SDP_BUSY;
+
+
+ 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((status = HID_HostAddDev (p_cb->addr, attr_mask, &hdl)) == HID_SUCCESS)
+ {
+ /* 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 = HID_SUCCESS;
+ }
+
+ }
+ else /* type of device is not supported */
+ status = HID_ERR_INVALID;
+ }
+
+ /* 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;
+ tHID_STATUS status = HID_ERR_SDP_BUSY;
+ tSDP_DI_GET_RECORD di_rec;
+
+ if (result == SDP_SUCCESS)
+ {
+#if BTA_HH_DEBUG
+ APPL_TRACE_EVENT2("bta_hh_di_sdp_cback: p_cb: %d result 0x%02x", \
+ p_cb, result);
+#endif
+ if (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);
+ }
+ }
+ if ((status = HID_HostGetSDPRecord(p_cb->addr,
+ bta_hh_cb.p_disc_db,
+ p_bta_hh_cfg->sdp_db_size,
+ bta_hh_sdp_cback)) != HID_SUCCESS)
+ {
+#if BTA_HH_DEBUG
+ APPL_TRACE_DEBUG1 ("bta_hh_di_sdp_cback: HID_HostGetSDPRecord failed: \
+ Status 0x%2X",status);
+#endif
+ status = BTA_HH_ERR_SDP;
+ utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+ }
+ }
+
+
+ if (status != HID_SUCCESS)
+ {
+ /* 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)
+{
+ tHID_STATUS status = HID_ERR_SDP_BUSY;
+ 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 = HID_SUCCESS;
+#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 ((status = 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;
+ }
+ }
+ 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 = HID_SUCCESS;
+ }
+ }
+
+ if (status != HID_SUCCESS)
+ 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;
+ tHID_STATUS 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 = p_data->status) == HID_SUCCESS)
+ {
+ /* not incoming connection doing SDP, initiate a HID connection */
+ if (!p_cb->incoming_conn)
+ {
+ /* set security level */
+ HID_HostSetSecurityLevel("", p_cb->sec_mask);
+
+ /* open HID connection */
+ if ((status = 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",status);
+#endif
+ /* open fail, remove device from management device list */
+ HID_HostRemoveDev( p_cb->hid_handle);
+
+ }
+ }
+ else /* incoming connection SDP finish */
+ {
+ bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
+ }
+ }
+
+ if (status != HID_SUCCESS)
+ {
+ /* receive SDP error */
+ if (p_data->status == HID_ERR_INVALID)
+ conn_dat.status = BTA_HH_ERR_TOD_UNSPT;
+ else
+ conn_dat.status = BTA_HH_ERR_SDP;
+
+ (* 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 ((conn.status = 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
+ 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:
+ 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:
+ 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_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 */
+ 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:/* 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;
+ /* deprecated for HID 1.1, shall not be sent out */
+ case HID_TRANS_GET_IDLE:
+ /* fall through */
+ case HID_TRANS_SET_IDLE:
+ APPL_TRACE_ERROR0("SET_IDLE, GET_IDLE is deprecated in HID 1.1")
+ 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..73e37a7
--- /dev/null
+++ b/bta/hh/bta_hh_api.c
@@ -0,0 +1,412 @@
+/*****************************************************************************/
+/* */
+/* Name: bta_hh_api.c */
+/* */
+/* Description: this file contains the HID HOST API in the subsystem of */
+/* BTA. */
+/* */
+/* Copyright (c) 2005, Broadcom Corp, All Rights Reserved. */
+/* WIDCOMM Bluetooth Core. Proprietary and confidential. */
+/*****************************************************************************/
+
+#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();
+
+ 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);
+}
+
+// btla-specific ++
+// ATTENTION:
+// BTA_HH_GET_IDLE_EVT and BTA_HH_SET_IDLE_EVT had been deprecated in the newer stack
+// btla apps will need to be changed accordingly for this
+// btla-specific --
+
+/*******************************************************************************
+**
+** 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..126ae4a
--- /dev/null
+++ b/bta/hh/bta_hh_cfg.c
@@ -0,0 +1,52 @@
+/*****************************************************************************
+**
+** Name: bta_hh_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the BTA Hid Host.
+**
+** Copyright (c) 2005, Broadcom Corp, All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..51dfad1
--- /dev/null
+++ b/bta/hh/bta_hh_int.h
@@ -0,0 +1,235 @@
+/****************************************************************************/
+/* */
+/* Name: bta_hh_int.h */
+/* */
+/* Function: this file contains BTA HID Host internal definitions */
+/* */
+/* Copyright (c) 2005, Broadcom Corp, All Rights Reserved. */
+/* WIDCOMM Bluetooth Core. Proprietary and confidential. */
+/* */
+/****************************************************************************/
+
+#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..648b10f
--- /dev/null
+++ b/bta/hh/bta_hh_main.c
@@ -0,0 +1,429 @@
+/*****************************************************************************
+**
+** Name: bta_hh_main.c
+**
+** Description: This file contains the HID host main functions and state
+** machine.
+**
+** Copyright (c) 2005, Broadcom Corp, All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..18ff0c3
--- /dev/null
+++ b/bta/hh/bta_hh_utils.c
@@ -0,0 +1,409 @@
+/*****************************************************************************
+**
+** Name: bta_hh_utils.c
+**
+** File: Implements the untility functions used by HID Host
+**
+** Copyright (c) 2005, Broadcom Corp, All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_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..cc14721
--- /dev/null
+++ b/bta/hl/bta_hl_act.c
@@ -0,0 +1,2794 @@
+/*****************************************************************************
+**
+** Name: bta_hl_act.c
+**
+** Description: This file contains the HeaLth device profile (HL) action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..65ab7bd
--- /dev/null
+++ b/bta/hl/bta_hl_api.c
@@ -0,0 +1,472 @@
+/*****************************************************************************
+**
+** Name: bta_hl_api.c
+**
+** Description: 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.
+**
+** Copyright (c) 2009-2011 Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..aab858f
--- /dev/null
+++ b/bta/hl/bta_hl_ci.c
@@ -0,0 +1,158 @@
+/*****************************************************************************
+**
+** Name: bta_hl_ci.c
+**
+** Description: This is the implementation file for the HeaLth device profile
+** (HL) subsystem call-in functions.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..03805d4
--- /dev/null
+++ b/bta/hl/bta_hl_int.h
@@ -0,0 +1,845 @@
+/*****************************************************************************
+**
+** Name: bta_hl_int.h
+**
+** Description: This is the private file for the message access
+** equipment (MSE) subsystem.
+**
+** Copyright (c) 1998-2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..3bfca86
--- /dev/null
+++ b/bta/hl/bta_hl_main.c
@@ -0,0 +1,1907 @@
+/*****************************************************************************
+**
+** Name: bta_hl_main.c
+**
+** Description: This file contains the HeaLth device profile main functions
+** and state machine.
+**
+** Copyright (c) 1998-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..765f6c1
--- /dev/null
+++ b/bta/hl/bta_hl_sdp.c
@@ -0,0 +1,429 @@
+/*****************************************************************************
+**
+** Name: bta_hl_sdp.c
+**
+** File: Implements the SDP functions used by HeaLth device profile
+**
+** Copyright (c) 1998-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..169e965
--- /dev/null
+++ b/bta/hl/bta_hl_utils.c
@@ -0,0 +1,3324 @@
+/*********************************************a********************************
+**
+** Name: bta_hl_utils.c
+**
+** Description: This file implements utility functions for the
+** HeaLth device profile (HL).
+**
+** Copyright (c) 2003-2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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(&reg, 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..0fd0cf8
--- /dev/null
+++ b/bta/include/bd.h
@@ -0,0 +1,89 @@
+/*****************************************************************************
+**
+** Name: bd.h
+**
+** Description: BD address services.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..32473ed
--- /dev/null
+++ b/bta/include/bta_ag_api.h
@@ -0,0 +1,496 @@
+/*****************************************************************************
+**
+** Name: bta_ag_api.h
+**
+** Description: This is the public interface file for the audio gateway
+** (AG) subsystem of BTA, Widcomm's Bluetooth application
+** layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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
+
+/* 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..5fc5a61
--- /dev/null
+++ b/bta/include/bta_ag_ci.h
@@ -0,0 +1,70 @@
+/*****************************************************************************
+**
+** Name: bta_ag_ci.h
+**
+** Description: This is the interface file for audio gateway call-in
+** functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..81927aa
--- /dev/null
+++ b/bta/include/bta_ag_co.h
@@ -0,0 +1,100 @@
+/*****************************************************************************
+**
+** Name: bta_ag_co.h
+**
+** Description: This is the interface file for audio gateway call-out
+** functions.
+**
+** Copyright (c) 2003-2006, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..8d7b71b
--- /dev/null
+++ b/bta/include/bta_api.h
@@ -0,0 +1,1712 @@
+/*****************************************************************************
+**
+** Name: bta_api.h
+**
+** Description: This is the public interface file for BTA, Widcomm's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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_FAX_SERVICE_ID 3 /* Fax 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 /* Advanced audio distribution */
+#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 --
+
+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_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 */
+// 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 BSA).
+**
+** 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_av_api.h b/bta/include/bta_av_api.h
new file mode 100644
index 0000000..f639d22
--- /dev/null
+++ b/bta/include/bta_av_api.h
@@ -0,0 +1,753 @@
+/*****************************************************************************
+**
+** Name: bta_av_api.h
+**
+** Description: This is the public interface file for the advanced
+** audio/video streaming (AV) subsystem of BTA, Widcomm's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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"
+#if( defined VDP_INCLUDED) && (VDP_INCLUDED == TRUE)
+#include "vdp_api.h"
+#endif
+
+/*****************************************************************************
+** 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 */
+
+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..c09e5e9
--- /dev/null
+++ b/bta/include/bta_av_ci.h
@@ -0,0 +1,62 @@
+/*****************************************************************************
+**
+** Name: bta_av_ci.h
+**
+** Description: This is the interface file for advanced audio/video call-in
+** functions.
+**
+** Copyright (c) 2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..2f41180
--- /dev/null
+++ b/bta/include/bta_av_co.h
@@ -0,0 +1,400 @@
+/*****************************************************************************
+**
+** Name: bta_av_co.h
+**
+** Description: This is the interface file for advanced audio/video call-out
+** functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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 Video Codec Information Element*/
+typedef struct
+{
+ UINT8 codec_type; /* Codec type */
+ UINT8 levels; /* level mask */
+} tBTA_AV_VIDEO_CFG;
+
+/* 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_video_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 video paths or for other
+** initialization purposes.
+**
+**
+** Returns Stream codec and content protection capabilities info.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_av_co_video_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);
+
+/*******************************************************************************
+**
+** 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);
+
+/*******************************************************************************
+**
+** 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_dg_api.h b/bta/include/bta_dg_api.h
new file mode 100644
index 0000000..3e8b2db
--- /dev/null
+++ b/bta/include/bta_dg_api.h
@@ -0,0 +1,198 @@
+/*****************************************************************************
+**
+** Name: bta_dg_api.h
+**
+** Description: This is the public interface file for the data gateway
+** (DG) subsystem of BTA, Widcomm's Bluetooth application
+** layer for mobile phones.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_DG_API_H
+#define BTA_DG_API_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* DG Callback events */
+#define BTA_DG_ENABLE_EVT 0 /* DG service is enabled. */
+#define BTA_DG_LISTEN_EVT 1 /* Server listen is started. */
+#define BTA_DG_OPENING_EVT 2 /* Client connection opening. */
+#define BTA_DG_OPEN_EVT 3 /* Connection has been opened. */
+#define BTA_DG_CLOSE_EVT 4 /* Connection has been closed. */
+
+typedef UINT8 tBTA_DG_EVT;
+
+/* Event associated with BTA_DG_LISTEN_EVT */
+typedef struct
+{
+ UINT16 handle; /* Handle associated with this server. */
+ UINT8 app_id; /* ID associated with call to BTA_DgListen(). */
+} tBTA_DG_LISTEN;
+
+/* Event associated with BTA_DG_OPENING_EVT */
+typedef struct
+{
+ UINT16 handle; /* Handle associated with this server. */
+ UINT8 app_id; /* ID associated with call to BTA_DgListen(). */
+} tBTA_DG_OPENING;
+
+
+/* Event associated with BTA_DG_OPEN_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* BD address of peer device. */
+ UINT16 handle; /* Handle associated with this server. */
+ tBTA_SERVICE_ID service; /* Service ID of opened service. */
+ UINT8 app_id; /* ID associated with call to BTA_DgListen(). */
+} tBTA_DG_OPEN;
+
+/* Event associated with BTA_DG_CLOSE_EVT */
+typedef struct
+{
+ UINT16 handle; /* Handle associated with this server. */
+ UINT8 app_id; /* ID associated with call to BTA_DgListen(). */
+} tBTA_DG_CLOSE;
+
+/* Union of all DG callback structures */
+typedef union
+{
+ tBTA_DG_LISTEN listen; /* Server listen is started. */
+ tBTA_DG_OPENING opening; /* Client connection opening. */
+ tBTA_DG_OPEN open; /* Connection has been opened. */
+ tBTA_DG_CLOSE close; /* Connection has been closed. */
+} tBTA_DG;
+
+/* DG callback */
+typedef void (tBTA_DG_CBACK)(tBTA_DG_EVT event, tBTA_DG *p_data);
+
+/* configuration structure */
+typedef struct
+{
+ UINT16 mtu[4]; /* MTU for SPP, DUN, FAX, LAP */
+
+} tBTA_DG_CFG;
+
+/* Number of DG servers */
+#ifndef BTA_DG_NUM_CONN
+#define BTA_DG_NUM_CONN 5
+#endif
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function BTA_DgEnable
+**
+** Description Enable the data gateway service. This function must be
+** called before any other functions in the DG API are called.
+** When the enable operation is complete the callback function
+** will be called with a BTA_DG_ENABLE_EVT. After the DG
+** service is enabled a server can be started by calling
+** BTA_DgListen().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DgEnable(tBTA_DG_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_DgDisable
+**
+** Description Disable the data gateway service. Before calling this
+** function all DG servers must be shut down by calling
+** BTA_DgShutdown().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DgDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_DgListen
+**
+** Description Create a DG server for DUN, FAX or SPP. After creating a
+** server peer devices can open an RFCOMM connection to the
+** server. When the listen operation has started the callback
+** function will be called with a BTA_DG_LISTEN_EVT providing
+** the handle associated with this server. The handle
+** identifies server when calling other DG functions such as
+** BTA_DgClose() or BTA_DgShutdown().
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DgListen(tBTA_SERVICE_ID service, tBTA_SEC sec_mask,
+ char *p_service_name, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_DgOpen
+**
+** Description Open a DG client connection to a peer device. BTA first
+** searches for the requested service on the peer device. If
+** the service name is specified it will also match the
+** service name. Then BTA initiates an RFCOMM connection to
+** the peer device. The handle associated with the connection
+** is returned with the BTA_DG_OPEN_EVT. If the connection
+** fails or closes at any time the callback function will be
+** called with a BTA_DG_CLOSE_EVT.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DgOpen(BD_ADDR bd_addr, tBTA_SERVICE_ID service,
+ tBTA_SEC sec_mask, char *p_service_name, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_DgClose
+**
+** Description Close a DG connection to a peer device. BTA will
+** close the RFCOMM connection to the peer device. Servers
+** will still be listening for subsequent connections.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DgClose(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function BTA_DgShutdown
+**
+** Description Shutdown a DG server previously started by calling
+** BTA_DgListen(). The server will no longer be available
+** to peer devices. If there is currently a connection open
+** to the server it will be closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DgShutdown(UINT16 handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_DG_API_H */
+
diff --git a/bta/include/bta_dg_ci.h b/bta/include/bta_dg_ci.h
new file mode 100644
index 0000000..1f52ab2
--- /dev/null
+++ b/bta/include/bta_dg_ci.h
@@ -0,0 +1,107 @@
+/*****************************************************************************
+**
+** Name: bta_dg_ci.h
+**
+** Description: This is the interface file for data gateway call-in
+** functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_DG_CI_H
+#define BTA_DG_CI_H
+
+#include "bta_dg_api.h"
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_dg_ci_tx_ready
+**
+** Description This function sends an event to DG indicating the phone is
+** ready for more data and DG should call bta_dg_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_dg_ci_tx_ready(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function bta_dg_ci_rx_ready
+**
+** Description This function sends an event to DG indicating the phone
+** has data available to send to DG and DG should call
+** bta_dg_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_dg_ci_rx_ready(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function bta_dg_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_dg_co_tx_write() or
+** bta_dg_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_dg_ci_tx_flow(UINT16 handle, BOOLEAN enable);
+
+/*******************************************************************************
+**
+** Function bta_dg_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 DG 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
+**
+*******************************************************************************/
+BTA_API extern void bta_dg_ci_rx_writebuf(UINT16 handle, BT_HDR *p_buf);
+
+/*******************************************************************************
+**
+** Function bta_dg_ci_control
+**
+** Description This function is called to send RS-232 signal information
+** to DG to be propagated over RFCOMM.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dg_ci_control(UINT16 handle, UINT8 signals, UINT8 values);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_DG_CI_H */
+
diff --git a/bta/include/bta_dg_co.h b/bta/include/bta_dg_co.h
new file mode 100644
index 0000000..667a01c
--- /dev/null
+++ b/bta/include/bta_dg_co.h
@@ -0,0 +1,198 @@
+/*****************************************************************************
+**
+** Name: bta_dg_co.h
+**
+** Description: This is the interface file for data gateway call-out
+** functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_DG_CO_H
+#define BTA_DG_CO_H
+
+#include "bta_dg_api.h"
+#include "l2c_api.h"
+#include "rfcdefs.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+/* RS-232 Signal Mask */
+#define BTA_DG_DTRDSR 0x01 /* DTR/DSR signal. */
+#define BTA_DG_RTSCTS 0x02 /* RTS/CTS signal. */
+#define BTA_DG_RI 0x04 /* Ring indicator signal. */
+#define BTA_DG_CD 0x08 /* Carrier detect signal. */
+
+/* RS-232 Signal Values */
+#define BTA_DG_DTRDSR_ON 0x01 /* DTR/DSR signal on. */
+#define BTA_DG_DTRDSR_OFF 0x00 /* DTR/DSR signal off. */
+#define BTA_DG_RTSCTS_ON 0x02 /* RTS/CTS signal on. */
+#define BTA_DG_RTSCTS_OFF 0x00 /* RTS/CTS signal off. */
+#define BTA_DG_RI_ON 0x04 /* Ring indicator signal on. */
+#define BTA_DG_RI_OFF 0x00 /* Ring indicator signal off. */
+#define BTA_DG_CD_ON 0x08 /* Carrier detect signal on. */
+#define BTA_DG_CD_OFF 0x00 /* Carrier detect signal off. */
+
+/* Data Flow Mask */
+#define BTA_DG_RX_PUSH_BUF 0x01 /* RX push with zero copy. */
+#define BTA_DG_RX_PULL 0x02 /* RX pull. */
+#define BTA_DG_TX_PUSH 0x00 /* TX push. */
+#define BTA_DG_TX_PUSH_BUF 0x10 /* TX push with zero copy. */
+#define BTA_DG_TX_PULL 0x20 /* TX pull. */
+
+/* BT_HDR buffer offset */
+#define BTA_DG_MIN_OFFSET (L2CAP_MIN_OFFSET + RFCOMM_MIN_OFFSET)
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_dg_co_init
+**
+** Description This callout function is executed by DG when a server is
+** started by calling BTA_DgListen(). 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_dg_co_init(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_dg_co_open
+**
+** Description This function is executed by DG when a connection to a
+** server 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_dg_co_open(UINT16 handle, UINT8 app_id, tBTA_SERVICE_ID service, UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function bta_dg_co_close
+**
+** Description This function is called by DG when a connection to a
+** server is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dg_co_close(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_dg_co_tx_path
+**
+** Description This function is called by DG 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. The implementation of this
+** function will typically call Bluetooth stack functions
+** PORT_Read() or PORT_ReadData() to read data from RFCOMM
+** and then a platform-specific function to send data that
+** data to the phone.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dg_co_tx_path(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_dg_co_rx_path
+**
+** Description This function is called by DG 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. The implementation of this
+** function will typically call a platform-specific function
+** to read data from the phone and then call Bluetooth stack
+** functions PORT_Write() or PORT_WriteData() to send data
+** to RFCOMM.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dg_co_rx_path(UINT16 handle, UINT8 app_id, UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function bta_dg_co_tx_write
+**
+** Description This function is called by DG 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_dg_co_tx_write(UINT16 handle, UINT8 app_id, UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function bta_dg_co_tx_writebuf
+**
+** Description This function is called by DG 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_dg_co_tx_writebuf(UINT16 handle, UINT8 app_id, BT_HDR *p_buf);
+
+/*******************************************************************************
+**
+** Function bta_dg_co_rx_flow
+**
+** Description This function is called by DG 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_dg_ci_rx_write() or bta_dg_ci_rx_writebuf()
+** until data flow is enabled again.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dg_co_rx_flow(UINT16 handle, UINT8 app_id, BOOLEAN enable);
+
+/*******************************************************************************
+**
+** Function bta_dg_co_control
+**
+** Description This function is called by DG to send RS-232 signal
+** information to the phone. This function allows these
+** signals to be propagated from the RFCOMM channel to the
+** phone. If the phone does not use these signals the
+** implementation of this function can do nothing.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_dg_co_control(UINT16 handle, UINT8 app_id, UINT8 signals, UINT8 values);
+
+#endif /* BTA_DG_CO_H */
+
diff --git a/bta/include/bta_dm_ci.h b/bta/include/bta_dm_ci.h
new file mode 100644
index 0000000..f662f17
--- /dev/null
+++ b/bta/include/bta_dm_ci.h
@@ -0,0 +1,69 @@
+/*****************************************************************************
+**
+** Name: bta_dm_ci.h
+**
+** Description: This is the interface file for device mananger call-in
+** functions.
+**
+** Copyright (c) 2006, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..cadf6bf
--- /dev/null
+++ b/bta/include/bta_dm_co.h
@@ -0,0 +1,262 @@
+/*****************************************************************************
+**
+** Name: bta_dm_co.h
+**
+** Description: This is the interface file for device mananger callout
+** functions.
+**
+** Copyright (c) 2006-2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..c0cb4f5
--- /dev/null
+++ b/bta/include/bta_fs_api.h
@@ -0,0 +1,32 @@
+/*****************************************************************************
+**
+** Name: bta_fs_api.h
+**
+** Description: This is the public interface file for the
+** file system of BTA, Widcomm's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2003 - 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..c60b3ba
--- /dev/null
+++ b/bta/include/bta_fs_ci.h
@@ -0,0 +1,244 @@
+/*****************************************************************************
+**
+** Name: bta_fs_ci.h
+**
+** Description: This is the interface file for file system
+** call-in functions.
+**
+** Copyright (c) 2003-2009, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..6b068df
--- /dev/null
+++ b/bta/include/bta_fs_co.h
@@ -0,0 +1,690 @@
+/*****************************************************************************
+**
+** Name: bta_fs_co.h
+**
+** Description: This is the interface file for the synchronization
+** server call-out functions.
+**
+** Copyright (c) 2003-2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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_ft_api.h b/bta/include/bta_ft_api.h
new file mode 100644
index 0000000..96ed66f
--- /dev/null
+++ b/bta/include/bta_ft_api.h
@@ -0,0 +1,724 @@
+/*****************************************************************************
+**
+** Name: bta_ft_api.h
+**
+** Description: This is the public interface file for the file transfer
+** (FT) server subsystem of BTA, Widcomm's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2003-2009, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_FT_API_H
+#define BTA_FT_API_H
+
+#include "bta_api.h"
+#include "btm_api.h"
+#if( defined BIP_INCLUDED) && (BIP_INCLUDED == TRUE)
+#include "bip_api.h"
+#endif
+#include "bta_sys.h"
+#include "bta_fs_co.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+#define BTA_FT_ENHANCED_VERSION 0x0102
+
+/**************************
+** Common Definitions
+***************************/
+/* Access response types */
+#define BTA_FT_ACCESS_ALLOW 0 /* Allow the requested operation */
+#define BTA_FT_ACCESS_FORBID 1 /* Disallow the requested operation */
+
+typedef UINT8 tBTA_FT_ACCESS;
+
+/* Access event operation types */
+#define BTA_FT_OPER_DEFAULT 0 /* Default mode */
+#define BTA_FT_OPER_PUT 1 /* Request is a PUT file */
+#define BTA_FT_OPER_GET 2 /* Request is a GET file */
+#define BTA_FT_OPER_DEL_FILE 3 /* Request is a DELETE file */
+#define BTA_FT_OPER_DEL_DIR 4 /* Request is a DELETE folder */
+#define BTA_FT_OPER_CHG_DIR 5 /* Request is a Change Folder */
+#define BTA_FT_OPER_MK_DIR 6 /* Request is a Make Folder */
+#define BTA_FT_OPER_COPY_ACT 7 /* Request is a Copy Action command */
+#define BTA_FT_OPER_MOVE_ACT 8 /* Request is a Move Action command */
+#define BTA_FT_OPER_SET_PERM 9 /* Request is a SetPermission Action command */
+
+typedef UINT8 tBTA_FT_OPER;
+
+#define BTA_FT_ACT_COPY OBX_ACT_COPY /* 0x00 Copy object */
+#define BTA_FT_ACT_MOVE OBX_ACT_MOVE /* 0x01 Move/rename object */
+#define BTA_FT_ACT_PERMISSION OBX_ACT_PERMISSION /* 0x02 Set object permission */
+typedef tOBX_ACTION tBTA_FTC_ACT;
+
+#define BTA_FTC_RESUME_NONCE 0xFFFFFFFF
+
+/* permission flags */
+#define BTA_FT_PERMISSION_READ OBX_PERMISSION_READ /* 0x01 */
+#define BTA_FT_PERMISSION_WRITE OBX_PERMISSION_WRITE /* 0x02 */
+#define BTA_FT_PERMISSION_DELETE OBX_PERMISSION_DELETE /* 0x04 */
+#define BTA_FT_PERMISSION_MODIFY OBX_PERMISSION_MODIFY /* 0x80 */
+
+/**************************
+** Server Definitions
+***************************/
+/* Extra Debug Code */
+#ifndef BTA_FTS_DEBUG
+#define BTA_FTS_DEBUG FALSE
+#endif
+
+#define BTA_FTS_OK 0
+#define BTA_FTS_FAIL 1
+typedef UINT8 tBTA_FTS_STATUS;
+
+/* Server callback function events */
+#define BTA_FTS_ENABLE_EVT 0 /* File transfer server is enabled. */
+#define BTA_FTS_OPEN_EVT 1 /* Connection to peer is open. */
+#define BTA_FTS_CLOSE_EVT 2 /* Connection to peer closed. */
+#define BTA_FTS_AUTH_EVT 3 /* Request for Authentication key and realm */
+#define BTA_FTS_ACCESS_EVT 4 /* Request for access to put a file */
+#define BTA_FTS_PROGRESS_EVT 5 /* Number of bytes read or written so far */
+#define BTA_FTS_PUT_CMPL_EVT 6 /* File Put complete */
+#define BTA_FTS_GET_CMPL_EVT 7 /* File Get complete */
+#define BTA_FTS_DEL_CMPL_EVT 8 /* Remove File or Folder complete */
+#define BTA_FTS_DISABLE_EVT 9 /* Reply to a disable api request */
+
+typedef UINT8 tBTA_FTS_EVT;
+
+/* Structure associated with BTA_FTS_xxx_CMPL_EVT */
+typedef struct
+{
+ char *p_name; /* file or folder name. */
+ tBTA_FTS_STATUS status;
+} tBTA_FTS_OBJECT;
+
+typedef struct
+{
+ UINT32 file_size; /* Total size of file (BTA_FS_LEN_UNKNOWN if unknown) */
+ UINT16 bytes; /* Number of bytes read or written since last progress event */
+} tBTA_FTS_PROGRESS;
+
+typedef struct
+{
+
+ UINT8 *p_userid;
+ UINT8 userid_len;
+ BOOLEAN userid_required; /* TRUE if user ID is required in response (rechallanged) */
+} tBTA_FTS_AUTH;
+
+typedef struct
+{
+ char *p_name; /* file name with fully qualified path */
+ UINT32 size; /* file size */
+ tBTM_BD_NAME dev_name; /* Name of device, "" if unknown */
+ tBTA_FT_OPER oper; /* operation (put) */
+ BD_ADDR bd_addr; /* Address of device */
+ char *p_dest_name; /* destination file name with fully qualified path (BTA_FT_OPER_COPY_ACT & BTA_FT_OPER_MOVE_ACT) */
+ UINT8 perms[BTA_FS_PERM_SIZE]; /* user/group/other permission (BTA_FT_OPER_SET_PERM) */
+} tBTA_FTS_ACCESS;
+
+typedef union
+{
+ tBTA_FTS_STATUS status;
+ tBTA_FTS_PROGRESS prog;
+ tBTA_FTS_AUTH auth;
+ tBTA_FTS_ACCESS access;
+ tBTA_FTS_OBJECT obj;
+ BD_ADDR bd_addr;
+} tBTA_FTS;
+
+/* Server callback function */
+typedef void tBTA_FTS_CBACK(tBTA_FTS_EVT event, tBTA_FTS *p_data);
+
+
+/**************************
+** Client Definitions
+***************************/
+/* Extra Debug Code */
+#ifndef BTA_FTC_DEBUG
+#define BTA_FTC_DEBUG FALSE
+#endif
+
+/* Additional paramters for BTA_FtcPutFile using BIP service */
+typedef union
+{
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ tBIP_IMAGE_DESC desc; /* when connectied with BIP service */
+#else
+ void* desc;
+#endif
+} tBTA_FTC_PARAM;
+
+/* Client callback function events */
+#define BTA_FTC_ENABLE_EVT 0 /* File transfer client is enabled. */
+#define BTA_FTC_OPEN_EVT 1 /* Connection to peer is open. */
+#define BTA_FTC_CLOSE_EVT 2 /* Connection to peer closed. */
+#define BTA_FTC_AUTH_EVT 3 /* Request for Authentication key and user id */
+#define BTA_FTC_LIST_EVT 4 /* Event contains a directory entry (tBTA_FTC_LIST) */
+#define BTA_FTC_PROGRESS_EVT 5 /* Number of bytes read or written so far */
+#define BTA_FTC_PUTFILE_EVT 6 /* File Put complete */
+#define BTA_FTC_GETFILE_EVT 7 /* File Get complete */
+#define BTA_FTC_BI_CAPS_EVT 8 /* BIP imaging capabilities */
+#define BTA_FTC_THUMBNAIL_EVT 9 /* BIP responder requests for the thumbnail version */
+#define BTA_FTC_CHDIR_EVT 10 /* Change Directory complete */
+#define BTA_FTC_MKDIR_EVT 11 /* Make Directory complete */
+#define BTA_FTC_REMOVE_EVT 12 /* Remove File/Directory complete */
+#define BTA_FTC_PHONEBOOK_EVT 13 /* Report the Application Parameters for BTA_FtcGetPhoneBook response */
+#define BTA_FTC_COPY_EVT 14 /* Copy File complete */
+#define BTA_FTC_MOVE_EVT 15 /* Move File complete */
+#define BTA_FTC_PERMISSION_EVT 16 /* Set File permission complete */
+
+
+typedef UINT8 tBTA_FTC_EVT;
+
+
+#define BTA_FTC_OK 0
+#define BTA_FTC_FAIL 1
+#define BTA_FTC_NO_PERMISSION 2
+#define BTA_FTC_NOT_FOUND 3
+#define BTA_FTC_FULL 4
+#define BTA_FTC_BUSY 5
+#define BTA_FTC_ABORTED 6
+#define BTA_FTC_SERVICE_UNAVL 7
+#define BTA_FTC_SDP_ERR 8
+#define BTA_FTC_OBX_ERR 9
+#define BTA_FTC_OBX_TOUT 10
+
+typedef UINT8 tBTA_FTC_STATUS;
+
+#define BTA_FTC_FLAG_NONE 0
+#define BTA_FTC_FLAG_BACKUP 1
+
+typedef UINT8 tBTA_FTC_FLAG;
+
+typedef struct
+{
+ tBTA_SERVICE_ID service; /* Connection is open with OPP, BIP, PBAP or FTP service */
+ UINT16 version;
+} tBTA_FTC_OPEN;
+
+#define BTA_FTC_FILTER_VERSION (1<<0) /* Version */
+#define BTA_FTC_FILTER_FN (1<<1) /* Formatted Name */
+#define BTA_FTC_FILTER_N (1<<2) /* Structured Presentation of Name */
+#define BTA_FTC_FILTER_PHOTO (1<<3) /* Associated Image or Photo */
+#define BTA_FTC_FILTER_BDAY (1<<4) /* Birthday */
+#define BTA_FTC_FILTER_ADR (1<<5) /* Delivery Address */
+#define BTA_FTC_FILTER_LABEL (1<<6) /* Delivery */
+#define BTA_FTC_FILTER_TEL (1<<7) /* Telephone Number */
+#define BTA_FTC_FILTER_EMAIL (1<<8) /* Electronic Mail Address */
+#define BTA_FTC_FILTER_MAILER (1<<9) /* Electronic Mail */
+#define BTA_FTC_FILTER_TZ (1<<10) /* Time Zone */
+#define BTA_FTC_FILTER_GEO (1<<11) /* Geographic Position */
+#define BTA_FTC_FILTER_TITLE (1<<12) /* Job */
+#define BTA_FTC_FILTER_ROLE (1<<13) /* Role within the Organization */
+#define BTA_FTC_FILTER_LOGO (1<<14) /* Organization Logo */
+#define BTA_FTC_FILTER_AGENT (1<<15) /* vCard of Person Representing */
+#define BTA_FTC_FILTER_ORG (1<<16) /* Name of Organization */
+#define BTA_FTC_FILTER_NOTE (1<<17) /* Comments */
+#define BTA_FTC_FILTER_REV (1<<18) /* Revision */
+#define BTA_FTC_FILTER_SOUND (1<<19) /* Pronunciation of Name */
+#define BTA_FTC_FILTER_URL (1<<20) /* Uniform Resource Locator */
+#define BTA_FTC_FILTER_UID (1<<21) /* Unique ID */
+#define BTA_FTC_FILTER_KEY (1<<22) /* Public Encryption Key */
+#define BTA_FTC_FILTER_ALL (0)
+typedef UINT32 tBTA_FTC_FILTER_MASK;
+
+enum
+{
+ BTA_FTC_FORMAT_CARD_21, /* vCard format 2.1 */
+ BTA_FTC_FORMAT_CARD_30, /* vCard format 3.0 */
+ BTA_FTC_FORMAT_MAX
+};
+typedef UINT8 tBTA_FTC_FORMAT;
+
+typedef struct
+{
+ UINT16 phone_book_size;
+ BOOLEAN pbs_exist; /* phone_book_size is present in the response */
+ UINT8 new_missed_calls;
+ BOOLEAN nmc_exist; /* new_missed_calls is present in the response */
+} tBTA_FTC_PB_PARAM;
+
+typedef struct
+{
+ tBTA_FTC_PB_PARAM *p_param;
+ UINT8 *data;
+ UINT16 len;
+ BOOLEAN final; /* If TRUE, entry is last of the series */
+ tBTA_FTC_STATUS status; /* Fields are valid when status is BTA_FTC_OK */
+} tBTA_FTC_LIST;
+
+enum
+{
+ BTA_FTC_ORDER_INDEXED = 0, /* indexed */
+ BTA_FTC_ORDER_ALPHANUM, /* alphanumeric */
+ BTA_FTC_ORDER_PHONETIC, /* phonetic */
+ BTA_FTC_ORDER_MAX
+};
+typedef UINT8 tBTA_FTC_ORDER;
+enum
+{
+ BTA_FTC_ATTR_NAME = 0, /* name */
+ BTA_FTC_ATTR_NUMBER, /* number */
+ BTA_FTC_ATTR_SOUND, /* sound */
+ BTA_FTC_ATTR_MAX
+};
+typedef UINT8 tBTA_FTC_ATTR;
+
+typedef struct
+{
+ UINT32 file_size; /* Total size of file (BTA_FS_LEN_UNKNOWN if unknown) */
+ UINT16 bytes; /* Number of bytes read or written since last progress event */
+} tBTA_FTC_PROGRESS;
+
+typedef struct
+{
+ UINT8 *p_realm;
+ UINT8 realm_len;
+ UINT8 realm_charset;
+ BOOLEAN userid_required; /* If TRUE, a user ID must be sent */
+} tBTA_FTC_AUTH;
+
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+typedef struct
+{
+ tBIP_IMAGING_CAPS *p_bi_caps; /* BIP imaging capabilities */
+} tBTA_FTC_CAPS;
+
+typedef struct
+{
+ UINT8 *p_name; /* the image file name */
+ tBIP_IMG_HDL_STR handle; /* The image’s handle assigned by BIP responder. */
+} tBTA_FTC_THUMB;
+#endif
+
+typedef union
+{
+ tBTA_FTC_STATUS status;
+ tBTA_FTC_OPEN open;
+ tBTA_FTC_LIST list;
+ tBTA_FTC_PROGRESS prog;
+ tBTA_FTC_AUTH auth;
+#if( defined BTA_BI_INCLUDED ) && (BTA_BI_INCLUDED == TRUE)
+ tBTA_FTC_CAPS bi_caps;
+ tBTA_FTC_THUMB thumb;
+#endif
+ tBTA_FTC_PB_PARAM pb;
+} tBTA_FTC;
+
+/* Client callback function */
+typedef void tBTA_FTC_CBACK(tBTA_FTC_EVT event, tBTA_FTC *p_data);
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************
+** Server Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function BTA_FtsEnable
+**
+** Description Enable the file transfer server. This function must be
+** called before any other functions in the FTS API are called.
+** When the enable operation is complete the callback function
+** will be called with an BTA_FTS_ENABLE_EVT event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtsEnable(tBTA_SEC sec_mask, const char *p_service_name,
+ const char *p_root_path, BOOLEAN enable_authen,
+ UINT8 realm_len, UINT8 *p_realm,
+ tBTA_FTS_CBACK *p_cback, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_FtsDisable
+**
+** Description Disable the file transfer server. If the server is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtsDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_FtsClose
+**
+** Description Close the current connection. This function is called if
+** the phone wishes to close the connection before the FT
+** client disconnects.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtsClose(void);
+
+/*******************************************************************************
+**
+** Function BTA_FtsUnauthRsp
+**
+** Description Sends an OBEX authentication challenge to the connected
+** OBEX client. Called in response to an BTA_FTS_AUTH_EVT event.
+** Used when "enable_authen" is set to TRUE in BTA_FtsEnable().
+**
+** Note: If the "userid_required" is TRUE in the BTA_FTS_AUTH_EVT
+** event, then p_userid is required, otherwise it is optional.
+**
+** p_password must be less than BTA_FTS_MAX_AUTH_KEY_SIZE (16 bytes)
+** p_userid must be less than OBX_MAX_REALM_LEN (defined in target.h)
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtsAuthRsp (char *p_password, char *p_userid);
+
+/*******************************************************************************
+**
+** Function BTA_FtsAccessRsp
+**
+** Description Sends a reply to an access request event (BTA_FTS_ACCESS_EVT).
+** This call MUST be made whenever the event occurs.
+**
+** Parameters oper - operation being accessed.
+** access - BTA_FT_ACCESS_ALLOW or BTA_FT_ACCESS_FORBID
+** p_name - Full path of file to pulled or pushed.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtsAccessRsp(tBTA_FT_OPER oper, tBTA_FT_ACCESS access,
+ char *p_name);
+
+
+/**************************
+** Client Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function BTA_FtcEnable
+**
+** Description Enable the file transfer client. This function must be
+** called before any other functions in the FTC API are called.
+** When the enable operation is complete the callback function
+** will be called with an BTA_FTC_ENABLE_EVT event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcEnable(tBTA_FTC_CBACK *p_cback, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_FtcDisable
+**
+** Description Disable the file transfer client. If the client is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_FtcOpen
+**
+** Description Open a connection to an FTP, PBAP, OPP or BIP server.
+** If parameter services is set to use both all services,
+** the client will attempt to connect to the device using
+** FTP first and then PBAP, OPP, BIP.
+** When the connection is open the callback function
+** will be called with a BTA_FTC_OPEN_EVT. If the connection
+** fails or otherwise is closed the callback function will be
+** called with a BTA_FTC_CLOSE_EVT.
+**
+** If the connection is opened with FTP profile and
+** bta_ft_cfg.auto_file_list is TRUE , the callback
+** function will be called with one or more BTA_FTC_LIST_EVT
+** containing directory list information formatted in XML as
+** described in the IrOBEX Spec, Version 1.2, section 9.1.2.3.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcOpen(BD_ADDR bd_addr, tBTA_SEC sec_mask,
+ tBTA_SERVICE_MASK services, BOOLEAN srm, UINT32 nonce);
+
+/*******************************************************************************
+**
+** Function BTA_FtcSuspend
+**
+** Description Suspend the current connection to the server.
+** This is allowed only for the sessions created by
+** BTA_FtcConnect with nonce!=0
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcSuspend(void);
+
+/*******************************************************************************
+**
+** Function BTA_FtcClose
+**
+** Description Close the current connection to the server. Aborts any
+** active file transfer.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcClose(void);
+
+/*******************************************************************************
+**
+** Function BTA_FtcCopyFile
+**
+** Description Invoke a Copy action on the server.
+** Create a copy of p_src and name it as p_dest
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcCopyFile(const char *p_src, const char *p_dest);
+
+/*******************************************************************************
+**
+** Function BTA_FtcMoveFile
+**
+** Description Invoke a Move action on the server.
+** Move/rename p_src to p_dest
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcMoveFile(const char *p_src, const char *p_dest);
+
+/*******************************************************************************
+**
+** Function BTA_FtcSetPermission
+**
+** Description Invoke a SetPermission action on the server.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcSetPermission(const char *p_src, UINT8 user, UINT8 group, UINT8 other);
+
+/*******************************************************************************
+**
+** Function BTA_FtcPutFile
+**
+** Description Send a file to the connected server.
+**
+** This function can only be used when the client is connected
+** in FTP, OPP and BIP mode.
+**
+** Note: File name is specified with a fully qualified path.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcPutFile(const char *p_name, tBTA_FTC_PARAM *p_param);
+
+/*******************************************************************************
+**
+** Function BTA_FtcGetPhoneBook
+**
+** Description Retrieve a PhoneBook from the peer device and copy it to the
+** local file system.
+**
+** This function can only be used when the client is connected
+** in PBAP mode.
+**
+** Note: local file name is specified with a fully qualified path.
+** Remote file name is absolute path in UTF-8 format
+** (telecom/pb.vcf or SIM1/telecom/pb.vcf).
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcGetPhoneBook(char *p_local_name, char *p_remote_name,
+ tBTA_FTC_FILTER_MASK filter, tBTA_FTC_FORMAT format,
+ UINT16 max_list_count, UINT16 list_start_offset);
+
+/*******************************************************************************
+**
+** Function BTA_FtcGetCard
+**
+** Description Retrieve a vCard from the peer device and copy it to the
+** local file system.
+**
+** This function can only be used when the client is connected
+** in PBAP mode.
+**
+** Note: local file name is specified with a fully qualified path.
+** Remote file name is relative path in UTF-8 format.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcGetCard(char *p_local_name, char *p_remote_name,
+ tBTA_FTC_FILTER_MASK filter, tBTA_FTC_FORMAT format);
+
+/*******************************************************************************
+**
+** Function BTA_FtcGetFile
+**
+** Description Retrieve a file from the peer device and copy it to the
+** local file system.
+**
+** This function can only be used when the client is connected
+** in FTP mode.
+**
+** Note: local file name is specified with a fully qualified path.
+** Remote file name is specified in UTF-8 format.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcGetFile(char *p_local_name, char *p_remote_name);
+
+/*******************************************************************************
+**
+** Function BTA_FtcChDir
+**
+** Description Change directory on the peer device.
+**
+** This function can only be used when the client is connected
+** in FTP and PBAP mode.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcChDir(char *p_dir, tBTA_FTC_FLAG flag);
+
+/*******************************************************************************
+**
+** Function BTA_FtcAuthRsp
+**
+** Description Sends a response to an OBEX authentication challenge to the
+** connected OBEX server. Called in response to an BTA_FTC_AUTH_EVT
+** event.
+**
+** Note: If the "userid_required" is TRUE in the BTA_FTC_AUTH_EVT event,
+** then p_userid is required, otherwise it is optional.
+**
+** p_password must be less than BTA_FTC_MAX_AUTH_KEY_SIZE (16 bytes)
+** p_userid must be less than OBX_MAX_REALM_LEN (defined in target.h)
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcAuthRsp (char *p_password, char *p_userid);
+
+/*******************************************************************************
+**
+** Function BTA_FtcListCards
+**
+** Description Retrieve a directory listing from the peer device.
+** When the operation is complete the callback function will
+** be called with one or more BTA_FTC_LIST_EVT events
+** containing directory list information formatted as described
+** in the PBAP Spec, Version 0.9, section 3.1.6.
+** This function can only be used when the client is connected
+** to a peer device.
+**
+** This function can only be used when the client is connected
+** in PBAP mode.
+**
+** Parameters p_dir - Name of directory to retrieve listing of.
+**
+** Returns void
+**
+*******************************************************************************/
+
+BTA_API extern void BTA_FtcListCards(char *p_dir, tBTA_FTC_ORDER order, char *p_value,
+ tBTA_FTC_ATTR attribute, UINT16 max_list_count,
+ UINT16 list_start_offset);
+
+/*******************************************************************************
+**
+** Function BTA_FtcListDir
+**
+** Description Retrieve a directory listing from the peer device.
+** When the operation is complete the callback function will
+** be called with one or more BTA_FTC_LIST_EVT events
+** containing directory list information formatted as described
+** in the IrOBEX Spec, Version 1.2, section 9.1.2.3.
+**
+** This function can only be used when the client is connected
+** in FTP mode.
+**
+** Parameters p_dir - Name of directory to retrieve listing of. If NULL,
+** the current working directory is retrieved.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcListDir(char *p_dir);
+
+/*******************************************************************************
+**
+** Function BTA_FtcAbort
+**
+** Description Aborts any active Put or Get file operation.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcAbort(void);
+
+/*******************************************************************************
+**
+** Function BTA_FtcRemove
+**
+** Description Remove a file or directory on the peer device. When the
+** operation is complete the status is returned with the
+** BTA_FTC_REMOVE_EVT event.
+**
+** This function can only be used when the client is connected
+** in FTP mode.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcRemove(char *p_name);
+
+/*******************************************************************************
+**
+** Function BTA_FtcMkDir
+**
+** Description Create a directory on the peer device. When the operation is
+** complete the status is returned with the BTA_FTC_MKDIR_EVT
+** event.
+**
+** This function can only be used when the client is connected
+** in FTP mode.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_FtcMkDir(char *p_dir);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_FT_API_H */
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
new file mode 100644
index 0000000..02284a5
--- /dev/null
+++ b/bta/include/bta_gatt_api.h
@@ -0,0 +1,1206 @@
+/*****************************************************************************
+**
+** Name: bta_gatt_api.h
+**
+** Description: This is the public interface file for BTA GATT.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..65941fc
--- /dev/null
+++ b/bta/include/bta_gattc_ci.h
@@ -0,0 +1,108 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_ci.h
+**
+** Description: This is the interface file for GATT
+** call-in functions.
+**
+** Copyright (c) 2003-2009, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..0aedf9f
--- /dev/null
+++ b/bta/include/bta_gattc_co.h
@@ -0,0 +1,89 @@
+/*****************************************************************************
+**
+** Name: bta_gattc_co.h
+**
+** Description: This is the interface file for BTA GATT client call-out
+** functions.
+**
+** Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..cb1ff76
--- /dev/null
+++ b/bta/include/bta_gatts_co.h
@@ -0,0 +1,70 @@
+/*****************************************************************************
+**
+** Name: bta_gatts_co.h
+**
+** Description: This is the interface file for BTA GATT server call-out
+** functions.
+**
+** Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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_hd_api.h b/bta/include/bta_hd_api.h
new file mode 100644
index 0000000..5fd7443
--- /dev/null
+++ b/bta/include/bta_hd_api.h
@@ -0,0 +1,289 @@
+/******************************************************************************
+**
+** File Name: bta_hd_api.h
+**
+** Description: This is the interface header file for the HID Device service.
+**
+** Copyright (c) 2002-2004, WIDCOMM Inc., All Rights Reserved.
+** WIDCOMM Bluetooth Core. Proprietary and confidential.
+**
+******************************************************************************/
+
+#ifndef BTA_HD_API_H
+#define BTA_HD_API_H
+
+#include "bt_types.h"
+#include "bta_api.h"
+#include "hidd_api.h"
+
+/*****************************************************************************/
+/* C O N S T A N T S */
+/*****************************************************************************/
+/* status values */
+#define BTA_HD_SUCCESS 0 /* operation successful */
+#define BTA_HD_FAIL 1 /* generic failure */
+#define BTA_HD_FAIL_SDP 2 /* service not found */
+
+typedef UINT8 tBTA_HD_STATUS;
+
+/* HD callback events */
+#define BTA_HD_ENABLE_EVT 0 /* HD enabled */
+#define BTA_HD_OPEN_EVT 1 /* connection opened */
+#define BTA_HD_CLOSE_EVT 2 /* connection closed */
+#define BTA_HD_UNPLUG_EVT 3 /* unplug */
+#define BTA_HD_DATA_EVT 4 /* Data received */
+#define BTA_HD_DATC_EVT 5 /* Data continueation received */
+
+typedef UINT8 tBTA_HD_EVT;
+
+enum
+{
+ BTA_HD_REPT_ID_SPEC, /* 0 */
+ BTA_HD_REPT_ID_KBD, /* 1: regular keyboard */
+ BTA_HD_REPT_ID_MOUSE, /* 2: mouse */
+ BTA_HD_REPT_ID_CONSUMER
+};
+typedef UINT8 tBTA_HD_REPT_ID;
+#define BTA_HD_REPT_ID_MAX BTA_HD_REPT_ID_CONSUMER
+
+
+#define BTA_HD_KBD_REPT_SIZE 9
+#define BTA_HD_MOUSE_REPT_SIZE 5
+
+
+/* Modifier Keys definition */
+#define BTA_HD_MDF_LCTRL 0x01 /* Left CTRL */
+#define BTA_HD_MDF_LSHIFT 0x02 /* Left SHIFT */
+#define BTA_HD_MDF_LALT 0x04 /* Left ALT */
+#define BTA_HD_MDF_LGUI 0x08 /* Left GUI */
+#define BTA_HD_MDF_RCTRL 0x10 /* Right CTRL */
+#define BTA_HD_MDF_RSHIFT 0x20 /* Right SHIFT */
+#define BTA_HD_MDF_RALT 0x40 /* Right ALT */
+#define BTA_HD_MDF_RGUI 0x80 /* Right GUI */
+
+/* keycode definition -
+ * See USB HID Usage Tables section 10: Keyboard/Keypad Page (0x07) */
+#define BTA_HD_KEYCODE_A 0x04 /* a A */
+#define BTA_HD_KEYCODE_B 0x05 /* b B */
+#define BTA_HD_KEYCODE_C 0x06 /* c C */
+#define BTA_HD_KEYCODE_D 0x07 /* d D */
+#define BTA_HD_KEYCODE_E 0x08 /* e E */
+#define BTA_HD_KEYCODE_F 0x09 /* f F */
+#define BTA_HD_KEYCODE_G 0x0A /* g G */
+#define BTA_HD_KEYCODE_H 0x0B /* h H */
+#define BTA_HD_KEYCODE_I 0x0C /* i I */
+#define BTA_HD_KEYCODE_J 0x0D /* j J */
+#define BTA_HD_KEYCODE_K 0x0E /* k K */
+#define BTA_HD_KEYCODE_L 0x0F /* l L */
+#define BTA_HD_KEYCODE_M 0x10 /* m M */
+#define BTA_HD_KEYCODE_N 0x11 /* n N */
+#define BTA_HD_KEYCODE_O 0x12 /* o O */
+#define BTA_HD_KEYCODE_P 0x13 /* p P */
+#define BTA_HD_KEYCODE_Q 0x14 /* q Q */
+#define BTA_HD_KEYCODE_R 0x15 /* r R */
+#define BTA_HD_KEYCODE_S 0x16 /* s S */
+#define BTA_HD_KEYCODE_T 0x17 /* t T */
+#define BTA_HD_KEYCODE_U 0x18 /* u U */
+#define BTA_HD_KEYCODE_V 0x19 /* v V */
+#define BTA_HD_KEYCODE_W 0x1A /* w W */
+#define BTA_HD_KEYCODE_X 0x1B /* x X */
+#define BTA_HD_KEYCODE_Y 0x1C /* y Y */
+#define BTA_HD_KEYCODE_Z 0x1D /* z Z */
+#define BTA_HD_KEYCODE_1 0x1E /* 1 ! */
+#define BTA_HD_KEYCODE_2 0x1F /* 2 @ */
+#define BTA_HD_KEYCODE_3 0x20 /* 3 # */
+#define BTA_HD_KEYCODE_4 0x21 /* 4 $ */
+#define BTA_HD_KEYCODE_5 0x22 /* 5 % */
+#define BTA_HD_KEYCODE_6 0x23 /* 6 ^ */
+#define BTA_HD_KEYCODE_7 0x24 /* 7 & */
+#define BTA_HD_KEYCODE_8 0x25 /* 8 * */
+#define BTA_HD_KEYCODE_9 0x26 /* 9 ( */
+#define BTA_HD_KEYCODE_0 0x27 /* 0 ) */
+#define BTA_HD_KEYCODE_ENTER 0x28 /* ENTER */
+#define BTA_HD_KEYCODE_ESC 0x29 /* ESC */
+#define BTA_HD_KEYCODE_BACKSPACE 0x2A /* BACKSPACE */
+#define BTA_HD_KEYCODE_TAB 0x2B /* TAB */
+#define BTA_HD_KEYCODE_SPACE 0x2C /* SPACE */
+#define BTA_HD_KEYCODE_MINUS 0x2D /* - _ */
+#define BTA_HD_KEYCODE_EQUAL 0x2E /* = + */
+#define BTA_HD_KEYCODE_LBRACKET 0x2F /* [ { */
+#define BTA_HD_KEYCODE_RBRACKET 0x30 /* ] } */
+#define BTA_HD_KEYCODE_BACKSLASH 0x31 /* \ | */
+#define BTA_HD_KEYCODE_SEMICOLUMN 0x33 /* ; : */
+#define BTA_HD_KEYCODE_QUOTE 0x34 /* ' " */
+#define BTA_HD_KEYCODE_TILT 0x35 /* ` ~ */
+#define BTA_HD_KEYCODE_COMMA 0x36 /* , < */
+#define BTA_HD_KEYCODE_DIR 0x37 /* . > */
+#define BTA_HD_KEYCODE_SLASH 0x38 /* / ? */
+#define BTA_HD_KEYCODE_F1 0x3A /* F1 */
+#define BTA_HD_KEYCODE_F2 0x3B /* F2 */
+#define BTA_HD_KEYCODE_F3 0x3C /* F3 */
+#define BTA_HD_KEYCODE_F4 0x3D /* F4 */
+#define BTA_HD_KEYCODE_F5 0x3E /* F5 */
+#define BTA_HD_KEYCODE_F6 0x3F /* F6 */
+#define BTA_HD_KEYCODE_F7 0x40 /* F7 */
+#define BTA_HD_KEYCODE_F8 0x41 /* F8 */
+#define BTA_HD_KEYCODE_F9 0x42 /* F9 */
+#define BTA_HD_KEYCODE_F10 0x43 /* F10 */
+#define BTA_HD_KEYCODE_F11 0x44 /* F11 */
+#define BTA_HD_KEYCODE_F12 0x45 /* F12 */
+#define BTA_HD_KEYCODE_HOME 0x4A /* HOME */
+#define BTA_HD_KEYCODE_PAGEUP 0x4B /* PAGE UP */
+#define BTA_HD_KEYCODE_END 0x4D /* END */
+#define BTA_HD_KEYCODE_PAGEDOWN 0x4E /* PAGE DOWN */
+#define BTA_HD_KEYCODE_RIGHTARROW 0x4F /* RIGHT ARROW */
+#define BTA_HD_KEYCODE_LEFTARROW 0x50 /* LEFT ARROW */
+#define BTA_HD_KEYCODE_DOWNARROW 0x51 /* DOWN ARROW */
+#define BTA_HD_KEYCODE_UPARROW 0x52 /* UP ARROW */
+#define BTA_HD_KEYCODE_POPUP 0x65 /* POPUP Menu */
+
+/* data associated with BTA_HD_OPEN_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr;
+} tBTA_HD_OPEN;
+
+/* data associated with BTA_HD_ENABLE_EVT */
+typedef struct
+{
+ tBTA_HD_STATUS status;
+} tBTA_HD_ENABLE;
+
+/* data associated with BTA_HD_CLOSE_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr;
+} tBTA_HD_CLOSE;
+
+/* data associated with BTA_HD_REPORT_EVT */
+typedef struct
+{
+ UINT8 *p_data;
+ UINT16 len;
+} tBTA_HD_REPORT;
+/*****************************************************************************/
+/* F U N C T I O N P R O T O T Y P E S */
+/*****************************************************************************/
+/* union of data associated with HD callback */
+typedef union
+{
+ tBTA_HD_ENABLE enable;
+ tBTA_HD_OPEN open;
+ tBTA_HD_CLOSE close;
+ tBTA_HD_REPORT data;
+} tBTA_HD;
+
+/* HD callback */
+typedef void (tBTA_HD_CBACK)(tBTA_HD_EVT event, tBTA_HD *p_data);
+
+/* HD configuration structure */
+typedef struct
+{
+ tHID_DEV_QOS_INFO qos;
+ tHID_DEV_SDP_INFO sdp_info;
+ BOOLEAN use_qos; /* use QoS */
+} tBTA_HD_CFG;
+
+/*******************************************************************************
+**
+** Function BTA_HdEnable
+**
+** Description Enable the HID Device service. When the enable
+** operation is complete the callback function will be
+** called with a BTA_HD_ENABLE_EVT. This function must
+** be called before other function in the HD API are
+** called.
+**
+** If all bytes of the specified bd_addr are 0xff, the
+** peer address is considered as unknown. The HID device listens
+** for incoming connection request.
+** Otherwise, The HID device initiates a connection toward the
+** specified bd_addr when BTA_HdOpen() is called.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_HdEnable(BD_ADDR bd_addr, tBTA_SEC sec_mask, const char *p_service_name,
+ tBTA_HD_CBACK *p_cback, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_HdDisable
+**
+** Description Disable the HID Device service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_HdDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_HdOpen
+**
+** Description Opens an HID Device connection to a peer device.
+** When connection is open, callback function is called
+** with a BTA_HD_OPEN_EVT.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_HdOpen(tBTA_SEC sec_mask);
+
+/*******************************************************************************
+**
+** Function BTA_HdClose
+**
+** Description Close the current connection a peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_HdClose(void);
+
+/*******************************************************************************
+**
+** Function BTA_HdSendRegularKey
+**
+** Description Send a key report to the connected host.
+** If auto_release is TRUE, assume the keyboard report must be
+** a key press. An associated key release report is also sent.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_HdSendRegularKey (UINT8 modifier, UINT8 key_code, BOOLEAN auto_release);
+
+/*******************************************************************************
+**
+** Function BTA_HdSendSpecialKey
+**
+** Description Send a special key report to the connected host.
+** The report is sent as a keyboard report.
+** If auto_release is TRUE, assume the keyboard report must be
+** a key press. An associated key release report is also sent.
+** If key_len is less than BTA_HD_KBD_REPT_SIZE, the key_seq
+** is padded with 0 until BTA_HD_KBD_REPT_SIZE.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_HdSendSpecialKey (UINT8 key_len, UINT8 * key_seq, BOOLEAN auto_release);
+
+/*******************************************************************************
+**
+** Function BTA_HdSendMouseReport
+**
+** Description Send a mouse report to the connected host
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_HdSendMouseReport (UINT8 is_left, UINT8 is_right, UINT8 is_middle,
+ INT8 delta_x, INT8 delta_y, INT8 delta_wheel);
+
+
+#endif /* BTA_HD_API_H */
diff --git a/bta/include/bta_hh_api.h b/bta/include/bta_hh_api.h
new file mode 100644
index 0000000..11dc35e
--- /dev/null
+++ b/bta/include/bta_hh_api.h
@@ -0,0 +1,444 @@
+/****************************************************************************
+**
+** Name: bta_hh_api.h
+**
+** Function: this file contains HID HOST side API definitions
+**
+** Copyright (c) 2002-2004, WIDCOMM Inc., All Rights Reserved.
+** WIDCOMM Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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 */
+/* leave 8, 9 gap due to deprecate of GET_IDLE and SET_IDLE */
+#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;
+
+/* 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_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..37d27ea
--- /dev/null
+++ b/bta/include/bta_hh_co.h
@@ -0,0 +1,60 @@
+/*****************************************************************************
+**
+** Name: bta_hh_co.h
+**
+** Description: This is the interface file for hid host call-out
+** functions.
+**
+** Copyright (c) 2005, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..a9cd312
--- /dev/null
+++ b/bta/include/bta_hl_api.h
@@ -0,0 +1,895 @@
+/*****************************************************************************
+**
+** Name: bta_hl_api.h
+**
+** Description: This is the public interface file for the HeaLth device profile
+** (HL) subsystem of BTA, Broadcom's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..6cb1451
--- /dev/null
+++ b/bta/include/bta_hl_ci.h
@@ -0,0 +1,112 @@
+/*****************************************************************************
+**
+** Name: bta_hl_ci.h
+**
+** Description: This is the interface file for the HL (HeaLth device profile)
+** subsystem call-in functions.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..464e99a
--- /dev/null
+++ b/bta/include/bta_hl_co.h
@@ -0,0 +1,219 @@
+/*****************************************************************************
+**
+** Name: bta_hl_co.h
+**
+** Description: This is the interface file for the HL (HeaLth device profile)
+** subsystem call-out functions.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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_ma_api.h b/bta/include/bta_ma_api.h
new file mode 100644
index 0000000..e0b413e
--- /dev/null
+++ b/bta/include/bta_ma_api.h
@@ -0,0 +1,691 @@
+/*****************************************************************************
+**
+** Name: bta_ma_api.h
+**
+** Description: This file contains the common API functions used
+** for the Message Access Profiles (MAP).
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_MA_API_H
+#define BTA_MA_API_H
+
+#include "bta_mse_api.h" /* For tBTA_MA_MSG_TYPE */
+#include <stdio.h>
+
+typedef struct
+{
+ UINT16 size; /* Size of the buffer */
+ UINT8 * p_buffer; /* Pointer to buffer */
+ UINT8 * p_next; /* Pointer to next byte to use in buffer */
+
+}tBTA_MA_MEM_STREAM;
+
+typedef struct
+{
+ int fd;
+
+}tBTA_MA_FILE_STREAM;
+
+/* Structure used for streaming data */
+typedef struct
+{
+#define STRM_TYPE_MEMORY 0
+#define STRM_TYPE_FILE 1
+
+ UINT8 type;
+
+#define STRM_SUCCESS 0
+#define STRM_ERROR_OVERFLOW 1
+#define STRM_ERROR_FILE 2
+
+ UINT8 status;
+
+ union
+ {
+ tBTA_MA_MEM_STREAM mem;
+ tBTA_MA_FILE_STREAM file;
+ } u;
+
+} tBTA_MA_STREAM;
+
+/*******************************************************************************
+**
+** bMessage functions
+**
+** Description The following API functions are generic in a sense that
+** they do not imply how the data is stored (to memory or
+** to file, etc.).
+**
+** They operate on a generic set of structure types. Though
+** the internal structure of those types are implementation
+** specific.
+**
+*******************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgCreate
+**
+** Description Create and initialize an instance of a tBTA_MA_BMSG structure.
+**
+** Parameters None
+**
+** Returns Pointer to a bMessage object, or NULL if this fails.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG * BTA_MaBmsgCreate(void);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgFree
+**
+** Description Destroy (free) the contents of a tBTA_MA_BMSG structure.
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgFree(tBTA_MA_BMSG * p_msg);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetReadSts
+**
+** Description Set the bmessage-readstatus-property value for the bMessage
+** object. If the 'read_sts' is TRUE then value will be "READ",
+** otherwise it is "UNREAD".
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+** read_sts - Read status TRUE- read FALSE - unread
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgSetReadSts(tBTA_MA_BMSG * p_msg, BOOLEAN read_sts);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetReadSts
+**
+** Description Get the bmessage-readstatus-property value for the bMessage
+** object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Read status (TRUE/FALSE) for the specified bMessage.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_MaBmsgGetReadSts(tBTA_MA_BMSG * p_msg);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetMsgType
+**
+** Description Set the bmessage-type-property value for the bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+** msg_type - Message type
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgSetMsgType(tBTA_MA_BMSG * p_msg, tBTA_MA_MSG_TYPE msg_type);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetMsgType
+**
+** Description Get the bmessage-type-property value for the specified
+** bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Message type
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_MSG_TYPE BTA_MaBmsgGetMsgType(tBTA_MA_BMSG * p_msg);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetFolder
+**
+** Description Set the bmessage-folder-property value for the bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+** p_folder - Pointer to a folder path
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgSetFolder(tBTA_MA_BMSG * p_msg, char * p_folder);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetFolder
+**
+** Description Get the bmessage-folder-property value for the specified
+** bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to folder path string, or NULL if it has not been set.
+**
+*******************************************************************************/
+BTA_API extern char * BTA_MaBmsgGetFolder(tBTA_MA_BMSG * p_msg);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddOrigToBmsg
+**
+** Description Add an originator to the bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to a new vCard structure, or NULL if this function
+** fails.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_VCARD * BTA_MaBmsgAddOrigToBmsg(tBTA_MA_BMSG * p_msg);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetOrigFromBmsg
+**
+** Description Get the first originator vCard information from the specified
+** bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to first 'originator vCard, or NULL not used.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetOrigFromBmsg(tBTA_MA_BMSG * p_msg);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddEnvToBmsg
+**
+** Description Add a new envelope to the bMessage object. This is the first
+** (top) level envelope. bMessage allows up to 3 levels of envelopes.
+** application should call BTA_MaBmsgAddEnvToEnv to add the 2nd
+** 3rd level enevelope.
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to a new envelope structure, or NULL if this
+** function fails.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgAddEnvToBmsg(tBTA_MA_BMSG * p_msg);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddEnvToEnv
+**
+** Description Add a child envelope to an existing envelope.
+**
+** Parameters p_envelope - Pointer to a parent envelope
+**
+** Returns Pointer to an envelope structure, or NULL if this
+** function fails.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgAddEnvToEnv(tBTA_MA_BMSG_ENVELOPE * p_envelope);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetEnv
+**
+** Description Get the pointer of the first level envelope.
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to the first level envelope structure, or NULL if it
+** does not exist
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgGetEnv(tBTA_MA_BMSG * p_msg);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextEnv
+**
+** Description Get the child envelope of the specified parent envelope.
+**
+** Parameters p_env - Pointer to a parent envelope
+**
+** Returns Pointer to a child enevelope. NULL if the
+** envelope does not have a 'child' envelope.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgGetNextEnv(tBTA_MA_BMSG_ENVELOPE * p_env);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddRecipToEnv
+**
+** Description Add recipient to the specified envelope.
+**
+** Parameters p_env - Pointer to a envelope
+**
+** Returns Pointer to a vCard structure. NULL if it
+** fails to allocate a vCard structure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_VCARD * BTA_MaBmsgAddRecipToEnv(tBTA_MA_BMSG_ENVELOPE * p_env);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetRecipFromEnv
+**
+** Description Get the first recipient's vCard from the specified envelope.
+**
+** Parameters p_env - Pointer to a envelope
+**
+** Returns Pointer to the first recipient's vCard structure. NULL if it
+** has not be set.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetRecipFromEnv(tBTA_MA_BMSG_ENVELOPE * p_env);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddBodyToEnv
+**
+** Description Add a message body to the specified envelope.
+**
+** Parameters p_env - Pointer to a envelope
+**
+** Returns Pointer to a message body structure.
+** NULL if it fails to allocate a message body structure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_BODY * BTA_MaBmsgAddBodyToEnv(tBTA_MA_BMSG_ENVELOPE * p_env);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyFromEnv
+**
+** Description Get the message body pointer from the specified envelope.
+**
+** Parameters p_env - Pointer to a envelope
+**
+** Returns Pointer to a message body structure.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_BODY * BTA_MaBmsgGetBodyFromEnv(tBTA_MA_BMSG_ENVELOPE * p_env);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetBodyEncoding
+**
+** Description Set the bmessage-body-encoding-property value for the bMessage
+** body.
+**
+** Parameters p_body - Pointer to a bMessage body
+** encoding - encoding scheme
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgSetBodyEncoding(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_BMSG_ENCODING encoding);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyEncoding
+**
+** Description Get the bmessage-body-encoding-property value for the specified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Message encoding scheme
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_ENCODING BTA_MaBmsgGetBodyEncoding(tBTA_MA_BMSG_BODY * p_body);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetBodyPartid
+**
+** Description Set the bmessage-body-part-ID value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+** part_id - Part ID (range: from 0 to 65535)
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgSetBodyPartid(tBTA_MA_BMSG_BODY * p_body, UINT16 part_id);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyPartid
+**
+** Description Get the bmessage-body-part-ID value for the specified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns The value of the Part ID
+**
+*******************************************************************************/
+BTA_API extern UINT16 BTA_MaBmsgGetBodyPartid(tBTA_MA_BMSG_BODY * p_body);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgIsBodyMultiPart
+**
+** Description Is this a multi-part body
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns TURE - if this is a multi-part body
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_MaBmsgIsBodyMultiPart(tBTA_MA_BMSG_BODY * p_body);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyCharset
+**
+** Description Get the bmessage-body-charset-property value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Charset
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgSetBodyCharset(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_CHARSET charset);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyCharset
+**
+** Description Get the bmessage-body-charset-property value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Charset
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_CHARSET BTA_MaBmsgGetBodyCharset(tBTA_MA_BMSG_BODY * p_body);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetBodyLanguage
+**
+** Description Set the bmessage-body-language-property value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+** Language - the language of the message
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgSetBodyLanguage(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_BMSG_LANGUAGE language);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyLanguage
+**
+** Description Get the bmessage-body-language-property value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns the language of the message
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_LANGUAGE BTA_MaBmsgGetBodyLanguage(tBTA_MA_BMSG_BODY * p_body);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddContentToBody
+**
+** Description Add a message content to the speicified bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Pointer to a message content.
+** NULL if it fails to allocate a message content buffer
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_CONTENT * BTA_MaBmsgAddContentToBody(tBTA_MA_BMSG_BODY * p_body);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetContentFromBody
+**
+** Description Get a message content from the speicified bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Pointer to a message content.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_CONTENT * BTA_MaBmsgGetContentFromBody(tBTA_MA_BMSG_BODY * p_body);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextContent
+**
+** Description Get the next message content from the speicified message content.
+**
+** Parameters p_content - Pointer to a message content
+**
+** Returns Pointer to a message content.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_CONTENT * BTA_MaBmsgGetNextContent(tBTA_MA_BMSG_CONTENT * p_content);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddMsgContent
+**
+** Description Add a text string to the speicified message content.
+**
+** Parameters p_content - Pointer to a message content
+** p_text - Pointer to a text string
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgAddMsgContent(tBTA_MA_BMSG_CONTENT * p_content, char * p_text);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetMsgContent
+**
+** Description Get the next text string from the speicified message content.
+**
+** Parameters p_content - Pointer to a message content
+**
+** Returns Pointer to the next text string.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+BTA_API extern char * BTA_MaBmsgGetMsgContent(tBTA_MA_BMSG_CONTENT * p_content);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextVcard
+**
+** Description Get the next vCard from the speicified vCard.
+**
+** Parameters p_vcard - Pointer to a vCard
+**
+** Returns Pointer to the next vCard.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+BTA_API extern char * BTA_MaBmsgGetNextMsgContent(tBTA_MA_BMSG_CONTENT * p_content);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextVcard
+**
+** Description Get the next vCard from the speicified vCard.
+**
+** Parameters p_vcard - Pointer to a vCard
+**
+** Returns Pointer to the next vCard.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetNextVcard(tBTA_MA_BMSG_VCARD * p_vcard);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetVcardVersion
+**
+** Description Set the vCard version for the speicified vCard.
+**
+** Parameters p_vcard - Pointer to a vCard
+** version - vcard version
+**
+** Returns None
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaBmsgSetVcardVersion(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_VERSION version);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardVersion
+**
+** Description Get the vCard version from the speicified vCard.
+**
+** Parameters p_vcard - Pointer to a vCard
+**
+** Returns vCard version number
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_VCARD_VERSION BTA_MaBmsgGetVcardVersion(tBTA_MA_BMSG_VCARD * p_vcard);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardProp
+**
+** Description Get the vCard property from the speicified vCard peoperty enum.
+**
+** Parameters p_vcard - Pointer to a vCard
+** prop - Indicate which vCard peoperty
+**
+** Returns Pointer to the vCard peoperty.
+** NULL if the vCard peoperty does not exist
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgAddVcardProp(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_PROP prop, char * p_value, char * p_param);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardProp
+**
+** Description Get the next vCard property from the speicified vCard peoperty.
+**
+** Parameters p_prop - Pointer to a vCard property
+**
+** Returns Pointer to the next vCard peoperty.
+** NULL if the next vCard peoperty does not exist
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgGetVcardProp(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_PROP prop);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextVcardProp
+**
+** Description Get the next vCard property from the speicified vCard peoperty.
+**
+** Parameters p_prop - Pointer to a vCard property
+**
+** Returns Pointer to the next vCard peoperty.
+** NULL if the next vCard peoperty does not exist
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgGetNextVcardProp(tBTA_MA_VCARD_PROPERTY * p_prop);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardPropValue
+**
+** Description Get the vCard property value from the speicified vCard peoperty.
+**
+** Parameters p_prop - Pointer to a vCard property
+**
+** Returns Pointer to the vCard peoperty value.
+** NULL if the vCard peoperty value has not been set.
+**
+*******************************************************************************/
+BTA_API extern char * BTA_MaBmsgGetVcardPropValue(tBTA_MA_VCARD_PROPERTY * p_prop);
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardPropParam
+**
+** Description Get the vCard property parameter from the speicified vCard peoperty.
+**
+** Parameters p_prop - Pointer to a vCard property
+**
+** Returns Poiter to the vCard peoperty parameter.
+** NULL if the vCard peoperty parameter has not been set.
+**
+*******************************************************************************/
+BTA_API extern char * BTA_MaBmsgGetVcardPropParam(tBTA_MA_VCARD_PROPERTY * p_prop);
+/*******************************************************************************
+**
+** Function BTA_MaBuildMapBmsgObj
+**
+** Description Builds a specification compliant bMessage object given a
+** generic bMessage internal structure.
+**
+** Parameters p_msg - pointer to bMessage object structure (input).
+** p_stream - Output stream.
+**
+** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_STATUS BTA_MaBuildMapBmsgObj(tBTA_MA_BMSG * p_msg, tBTA_MA_STREAM * p_stream);
+/*******************************************************************************
+**
+** Function bta_ma_parse_map_bmsg_obj
+**
+** Description Parses a bMessage object from a stream into a generic
+** bMessage internal structure.
+**
+** Parameters p_msg - pointer to bMessage object structure (output).
+** p_stream - Input stream.
+**
+** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not.
+**
+*******************************************************************************/
+BTA_API extern tBTA_MA_STATUS BTA_MaParseMapBmsgObj(tBTA_MA_BMSG * p_msg, tBTA_MA_STREAM * p_stream);
+
+/*******************************************************************************
+**
+** Function BTA_MaInitMemStream
+**
+** Description Initializes a memory based stream
+**
+** Parameters p_stream - pointer to stream information.
+** p_buffer - pointer to buffer to be manipulated.
+** size - size of buffer pointed to by 'p_buffer'.
+**
+** Returns TRUE if stream is successfully initialized
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_MaInitMemStream(tBTA_MA_STREAM * p_stream,
+ UINT8 * p_buffer,
+ UINT16 size);
+/*******************************************************************************
+**
+** Function BTA_MaInitFileStream
+**
+** Description Initializes a file stream
+**
+** Parameters p_stream - pointer to stream information.
+** p_filename - Full pathname to file to use.
+** oflags - permissions and mode (see constants above)
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_MaInitFileStream(tBTA_MA_STREAM * p_stream,
+ const char *p_path,
+ int oflags);
+/*******************************************************************************
+**
+** Function BTA_MaCloseStream
+**
+** Description Close a stream (do any necessary clean-up.
+**
+** Parameters p_stream - pointer to stream information.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_MaCloseStream(tBTA_MA_STREAM * p_stream);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_BMSG_API_H */
diff --git a/bta/include/bta_ma_co.h b/bta/include/bta_ma_co.h
new file mode 100644
index 0000000..442d106
--- /dev/null
+++ b/bta/include/bta_ma_co.h
@@ -0,0 +1,91 @@
+/*****************************************************************************
+**
+** Name: bta_ma_co.h
+**
+** Description: This is the interface file for the Message Access Profile
+** common call-out functions.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_MA_CO_H
+#define BTA_MA_CO_H
+
+#include <stdio.h>
+
+/*****************************************************************************
+**
+** Utility functions for converting types to strings.
+**
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ma_co_open
+**
+** Description Open a file.
+**
+** Parameters p_path - Full path of file to open.
+** oflags - file open flags.
+**
+** Returns file descriptor. BTA_FS_INVALID_FD if open fails.
+**
+*******************************************************************************/
+ BTA_API extern int bta_ma_co_open(const char *p_path, int oflags);
+
+/*******************************************************************************
+**
+** Function bta_ma_co_write
+**
+** Description Write data to file.
+**
+** Parameters fd - file descriptor.
+** buffer - data to write.
+** size - size of data to write (in bytes).
+**
+** Returns Number of bytes written.
+**
+*******************************************************************************/
+ BTA_API extern int bta_ma_co_write(int fd, const void *buffer, int size);
+
+/*******************************************************************************
+**
+** Function bta_ma_co_read
+**
+** Description Read data from file.
+**
+** Parameters fd - file descriptor.
+** buffer - to receive data.
+** size - amount of data to read (in bytes).
+**
+** Returns Number of bytes read.
+**
+*******************************************************************************/
+ BTA_API extern int bta_ma_co_read(int fd, void *buffer, int size);
+
+/*******************************************************************************
+**
+** Function bta_ma_co_close
+**
+** Description Close the file.
+**
+** Parameters fd - file descriptor.
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void bta_ma_co_close(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_MA_FILE_H */
+
+
diff --git a/bta/include/bta_ma_def.h b/bta/include/bta_ma_def.h
new file mode 100644
index 0000000..7202385
--- /dev/null
+++ b/bta/include/bta_ma_def.h
@@ -0,0 +1,479 @@
+/*****************************************************************************
+**
+** Name: bta_ma_def.h
+**
+** Description: This file contains the common definitions for the Message Access
+** profile (MA) related SW modules
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_MA_DEF_H
+#define BTA_MA_DEF_H
+
+#include "obx_api.h"
+#include "bta_api.h"
+#include "btm_api.h"
+#include "bta_sys.h"
+#include "bta_fs_co.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+
+#define BTA_MA_HANDLE_SIZE 8
+
+typedef UINT8 tBTA_MA_MSG_HANDLE[BTA_MA_HANDLE_SIZE];
+
+typedef tOBX_HANDLE tBTA_MA_SESS_HANDLE;
+
+typedef UINT8 tBTA_MA_INST_ID;
+
+#define BTA_MA_STATUS_OK 0
+#define BTA_MA_STATUS_FAIL 1 /* Used to pass all other errors */
+#define BTA_MA_STATUS_ABORTED 2
+#define BTA_MA_STATUS_NO_RESOURCE 3
+#define BTA_MA_STATUS_EACCES 4
+#define BTA_MA_STATUS_ENOTEMPTY 5
+#define BTA_MA_STATUS_EOF 6
+#define BTA_MA_STATUS_EODIR 7
+#define BTA_MA_STATUS_ENOSPACE 8 /* Returned in bta_fs_ci_open if no room */
+#define BTA_MA_STATUS_DUPLICATE_ID 9
+#define BTA_MA_STATUS_ID_NOT_FOUND 10
+#define BTA_MA_STATUS_FULL 11 /* reach the max packet size */
+
+typedef UINT8 tBTA_MA_STATUS;
+
+#define BTA_MA_OPER_NONE 0
+#define BTA_MA_OPER_GET_MSG 1
+#define BTA_MA_OPER_PUSH_MSG 2
+
+typedef UINT8 tBTA_MA_OPER;
+
+/* mode field in tBTA_MSE_CO_FOLDER_ENTRY (OR'd together) */
+#define BTA_MA_A_RDONLY 1
+#define BTA_MA_A_DIR 2 /* Entry is a sub directory */
+
+
+/* message status inficator */
+#define BTA_MA_STS_INDTR_READ 0
+#define BTA_MA_STS_INDTR_DELETE 1
+typedef UINT8 tBTA_MA_STS_INDCTR;
+
+/* message status value */
+#define BTA_MA_STS_VALUE_NO 0
+#define BTA_MA_STS_VALUE_YES 1
+typedef UINT8 tBTA_MA_STS_VALUE;
+
+/* notification status */
+enum
+{
+ BTA_MA_NOTIF_OFF = 0,
+ BTA_MA_NOTIF_ON,
+ BTA_MA_NOTIF_MAX
+
+};
+typedef UINT8 tBTA_MA_NOTIF_STATUS;
+
+
+/* Access response types */
+enum
+{
+ BTA_MA_ACCESS_TYPE_ALLOW = 0, /* Allow the requested operation */
+ BTA_MA_ACCESS_TYPE_FORBID /* Disallow the requested operation */
+};
+
+typedef UINT8 tBTA_MA_ACCESS_TYPE;
+
+/* Structure for in progress related event*/
+typedef struct
+{
+ UINT32 obj_size; /* Total size of object 0 if unknow*/
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ UINT16 bytes; /* Number of bytes read or written since last progress event */
+} tBTA_MA_IN_PROG;
+
+
+/* Message type see SDP supported message type */
+#define BTA_MA_MSG_TYPE_EMAIL (1<<0)
+#define BTA_MA_MSG_TYPE_SMS_GSM (1<<1)
+#define BTA_MA_MSG_TYPE_SMS_CDMA (1<<2)
+#define BTA_MA_MSG_TYPE_MMS (1<<3)
+typedef UINT8 tBTA_MA_MSG_TYPE;
+
+#define BTA_MA_MAX_FILTER_TEXT_SIZE 255
+
+/* Message type mask for FilterMessageType in Application parameter */
+#define BTA_MA_MSG_TYPE_MASK_SMS_GSM (1<<0)
+#define BTA_MA_MSG_TYPE_MASK_SMS_CDMA (1<<1)
+#define BTA_MA_MSG_TYPE_MASK_EMAIL (1<<2)
+#define BTA_MA_MSG_TYPE_MASK_MMS (1<<3)
+
+
+typedef UINT8 tBTA_MA_MSG_TYPE_MASK;
+
+
+
+/* Parameter Mask for Messages-Listing */
+#define BTA_MA_ML_MASK_SUBJECT (1<<0)
+#define BTA_MA_ML_MASK_DATETIME (1<<1)
+#define BTA_MA_ML_MASK_SENDER_NAME (1<<2)
+#define BTA_MA_ML_MASK_SENDER_ADDRESSING (1<<3)
+#define BTA_MA_ML_MASK_RECIPIENT_NAME (1<<4)
+#define BTA_MA_ML_MASK_RECIPIENT_ADDRESSING (1<<5)
+#define BTA_MA_ML_MASK_TYPE (1<<6)
+#define BTA_MA_ML_MASK_SIZE (1<<7)
+#define BTA_MA_ML_MASK_RECEPTION_STATUS (1<<8)
+#define BTA_MA_ML_MASK_TEXT (1<<9)
+#define BTA_MA_ML_MASK_ATTACHMENT_SIZE (1<<10)
+#define BTA_MA_ML_MASK_PRIORITY (1<<11)
+#define BTA_MA_ML_MASK_READ (1<<12)
+#define BTA_MA_ML_MASK_SENT (1<<13)
+#define BTA_MA_ML_MASK_PROTECTED (1<<14)
+#define BTA_MA_ML_MASK_REPLYTO_ADDRESSING (1<<15)
+
+typedef UINT32 tBTA_MA_ML_MASK;
+
+/* Read status used for message list */
+enum
+{
+ BTA_MA_READ_STATUS_NO_FILTERING = 0,
+ BTA_MA_READ_STATUS_UNREAD = 1,
+ BTA_MA_READ_STATUS_READ = 2
+};
+typedef UINT8 tBTA_MA_READ_STATUS;
+
+/* Priority status used for filtering message list */
+enum
+{
+ BTA_MA_PRI_STATUS_NO_FILTERING = 0,
+ BTA_MA_PRI_STATUS_HIGH = 1,
+ BTA_MA_PRI_STATUS_NON_HIGH = 2
+};
+typedef UINT8 tBTA_MA_PRI_STATUS;
+
+#define BTA_MA_LTIME_LEN 15
+typedef struct
+{
+ tBTA_MA_ML_MASK parameter_mask;
+ UINT16 max_list_cnt;
+ UINT16 list_start_offset;
+ UINT8 subject_length; /* valid range 1...255 */
+ tBTA_MA_MSG_TYPE_MASK msg_mask;
+ char period_begin[BTA_MA_LTIME_LEN+1]; /* "yyyymmddTHHMMSS", or "" if none */
+ char period_end[BTA_MA_LTIME_LEN+1]; /* "yyyymmddTHHMMSS", or "" if none */
+ tBTA_MA_READ_STATUS read_status;
+ char recipient[BTA_MA_MAX_FILTER_TEXT_SIZE+1]; /* "" if none */
+ char originator[BTA_MA_MAX_FILTER_TEXT_SIZE+1];/* "" if none */
+ tBTA_MA_PRI_STATUS pri_status;
+} tBTA_MA_MSG_LIST_FILTER_PARAM;
+
+/* enum for charset used in GetMEssage */
+enum
+{
+ BTA_MA_CHARSET_NATIVE = 0,
+ BTA_MA_CHARSET_UTF_8 = 1,
+ BTA_MA_CHARSET_UNKNOWN,
+ BTA_MA_CHARSET_MAX
+};
+typedef UINT8 tBTA_MA_CHARSET;
+
+/* enum for fraction request used in GetMEssage */
+enum
+{
+ BTA_MA_FRAC_REQ_FIRST = 0,
+ BTA_MA_FRAC_REQ_NEXT = 1,
+ BTA_MA_FRAC_REQ_NO, /* this is not a fraction request */
+ BTA_MA_FRAC_REQ_MAX
+};
+typedef UINT8 tBTA_MA_FRAC_REQ;
+
+/* enum for fraction delivery used in GetMEssage */
+enum
+{
+ BTA_MA_FRAC_DELIVER_MORE = 0,
+ BTA_MA_FRAC_DELIVER_LAST = 1,
+ BTA_MA_FRAC_DELIVER_NO, /* this is not a fraction deliver*/
+ BTA_MA_FRAC_DELIVER_MAX
+};
+typedef UINT8 tBTA_MA_FRAC_DELIVER;
+
+
+typedef struct
+{
+ BOOLEAN attachment;
+ tBTA_MA_MSG_HANDLE handle;
+ tBTA_MA_CHARSET charset;
+ tBTA_MA_FRAC_REQ fraction_request;
+} tBTA_MA_GET_MSG_PARAM;
+
+#define BTA_MA_RETRY_OFF 0
+#define BTA_MA_RETRY_ON 1
+#define BTA_MA_RETRY_UNKNOWN 0xff
+typedef UINT8 tBTA_MA_RETRY_TYPE;
+
+
+#define BTA_MA_TRANSP_OFF 0
+#define BTA_MA_TRANSP_ON 1
+#define BTA_MA_TRANSP_UNKNOWN 0xff
+typedef UINT8 tBTA_MA_TRANSP_TYPE;
+
+typedef struct
+{
+ char *p_folder; /* current or child folder
+ for current folder set
+ *p_folder = ""
+ */
+ char *p_msg_name; /* for MCE use only*/
+ tBTA_MA_TRANSP_TYPE transparent;
+ tBTA_MA_RETRY_TYPE retry;
+ tBTA_MA_CHARSET charset;
+
+} tBTA_MA_PUSH_MSG_PARAM;
+
+/* get or push message multi-packet status */
+enum
+{
+ BTA_MA_MPKT_STATUS_MORE = 0,
+ BTA_MA_MPKT_STATUS_LAST,
+ BTA_MA_MPKT_MAX
+};
+
+typedef UINT8 tBTA_MA_MPKT_STATUS;
+
+/* definitions for directory navigation */
+#define BTA_MA_DIR_NAV_ROOT_OR_DOWN_ONE_LVL 2
+#define BTA_MA_DIR_NAV_UP_ONE_LVL 3
+
+typedef UINT8 tBTA_MA_DIR_NAV;
+
+enum
+{
+ BTA_MA_ATTACH_OFF = 0,
+ BTA_MA_ATTACH_ON
+};
+typedef UINT8 tBTA_MA_ATTACH_TYPE;
+
+/* MAS tag ID in application parameters header definition */
+#define BTA_MA_APH_MAX_LIST_COUNT 0x01 /* MaxListCount 2 bytes 0x0000 to 0xFFFF */
+#define BTA_MA_APH_START_STOFF 0x02 /* StartOffset 2 bytes 0x0000 to 0xFFFF */
+#define BTA_MA_APH_FILTER_MSG_TYPE 0x03 /* SearchAttribute 1 byte 1,2,4 */
+#define BTA_MA_APH_FILTER_PRD_BEGIN 0x04 /* Filter Period Begin variable */
+#define BTA_MA_APH_FILTER_PRD_END 0x05 /* Filter Period End variable */
+#define BTA_MA_APH_FILTER_READ_STS 0x06 /* Filter read status 1 byte 0, 1, 2 */
+#define BTA_MA_APH_FILTER_RECEIP 0x07 /* FilterRecipient variable */
+#define BTA_MA_APH_FILTER_ORIGIN 0x08 /* FilterOriginator variable */
+#define BTA_MA_APH_FILTER_PRIORITY 0x09 /* FilterPriority 1 byte */
+#define BTA_MA_APH_ATTACH 0x0a /* Attachment 1 byte */
+#define BTA_MA_APH_TRANSPARENT 0x0b /* transparent 1 byte */
+#define BTA_MA_APH_RETRY 0x0c /* retry 1 byte */
+#define BTA_MA_APH_NEW_MSG 0x0d /* NewMessage 1 byte */
+#define BTA_MA_APH_NOTIF_STATUS 0x0e /* Notification Status 1 byte */
+#define BTA_MA_APH_MAS_INST_ID 0x0f /* MAS instance ID 1 byte 0 ... 255 */
+#define BTA_MA_APH_PARAM_MASK 0x10 /* Parameter mask 2 bytes */
+#define BTA_MA_APH_FOLDER_LST_SIZE 0x11 /* Folder Listing Size 2 bytes */
+#define BTA_MA_APH_MSG_LST_SIZE 0x12 /* Message Listing Size 2 bytes */
+#define BTA_MA_APH_SUBJ_LEN 0x13 /* Subject Length 1 byte */
+#define BTA_MA_APH_CHARSET 0x14 /* Character Set 1 byte :0, 1 */
+#define BTA_MA_APH_FRAC_REQ 0x15 /* Fraction request 1 byte :0, 1 */
+#define BTA_MA_APH_FRAC_DELVR 0x16 /* Fraction delivery 1 byte :0, 1 */
+#define BTA_MA_APH_STS_INDCTR 0x17 /* Status Indicator 1 byte */
+#define BTA_MA_APH_STS_VALUE 0x18 /* Status Value 1 byte: 0, 1 */
+#define BTA_MA_APH_MSE_TIME 0x19 /* MSETime variable */
+
+#define BTA_MA_BODY_FILLER_BYTE 0x30
+
+/* MAS type header */
+#define BTA_MA_HDR_TYPE_NOTIF_REG "x-bt/MAP-NotificationRegistration"
+#define BTA_MA_HDR_TYPE_MSG_UPDATE "x-bt/MAP-messageUpdate"
+#define BTA_MA_HDR_TYPE_EVENT_RPT "x-bt/MAP-event-report"
+#define BTA_MA_HDR_TYPE_MSG_LIST "x-bt/MAP-msg-listing"
+#define BTA_MA_HDR_TYPE_MSG "x-bt/message"
+#define BTA_MA_HDR_TYPE_MSG_STATUS "x-bt/messageStatus"
+#define BTA_MA_HDR_TYPE_FOLDER_LIST "x-obex/folder-listing"
+
+#define BTA_MAS_MESSAGE_ACCESS_TARGET_UUID "\xBB\x58\x2B\x40\x42\x0C\x11\xDB\xB0\xDE\x08\x00\x20\x0C\x9A\x66"
+#define BTA_MAS_MESSAGE_NOTIFICATION_TARGET_UUID "\xBB\x58\x2B\x41\x42\x0C\x11\xDB\xB0\xDE\x08\x00\x20\x0C\x9A\x66"
+#define BTA_MAS_UUID_LENGTH 16
+#define BTA_MAS_DEFAULT_VERSION 0x0100
+
+#define BTA_MA_NOTIF_STS_TAG_ID 0x0E
+#define BTA_MA_NOTIF_STS_LEN 0x01
+#define BTA_MA_NOTIF_STS_ON 0x01
+#define BTA_MA_NOTIF_STS_OFF 0x00
+
+#define BTA_MA_NAS_INST_ID_TAG_ID 0x0F
+#define BTA_MA_NAS_INST_ID_LEN 0x01
+
+#define BTA_MA_DEFAULT_MAX_LIST_CNT 1024
+
+
+#define BTA_MA_64BIT_HEX_STR_SIZE (16+1)
+#define BTA_MA_32BIT_HEX_STR_SIZE (8+1)
+
+
+
+/*******************************************************************************
+**
+** bMessage types
+**
+** Description The following types are designed to hold data in memory.
+** The internal structure of these types are implementation
+** specific.
+**
+*******************************************************************************/
+
+enum
+{
+ BTA_MA_BMSG_ENC_8BIT = 0, /* Used for Email/MMS */
+
+ BTA_MA_BMSG_ENC_G7BIT, /* Used for GSM-SMS */
+ BTA_MA_BMSG_ENC_G7BITEXT,
+ BTA_MA_BMSG_ENC_GUCS2,
+ BTA_MA_BMSG_ENC_G8BIT,
+
+ BTA_MA_BMSG_ENC_C8BIT, /* Used for CDMA-SMS */
+ BTA_MA_BMSG_ENC_CEPM,
+ BTA_MA_BMSG_ENC_C7ASCII,
+ BTA_MA_BMSG_ENC_CIA5,
+ BTA_MA_BMSG_ENC_CUNICODE,
+ BTA_MA_BMSG_ENC_CSJIS,
+ BTA_MA_BMSG_ENC_CKOREAN,
+ BTA_MA_BMSG_ENC_CLATINHEB,
+ BTA_MA_BMSG_ENC_CLATIN,
+
+ BTA_MA_BMSG_ENC_UNKNOWN
+};
+typedef UINT8 tBTA_MA_BMSG_ENCODING;
+
+enum
+{
+ BTA_MA_BMSG_LANG_UNSPECIFIED = 0,
+
+ BTA_MA_BMSG_LANG_UNKNOWN,
+ BTA_MA_BMSG_LANG_SPANISH, /* GSM-SMS or CDMA-SMS */
+
+ BTA_MA_BMSG_LANG_TURKISH, /* GSM-SMS only */
+ BTA_MA_BMSG_LANG_PORTUGUESE,
+
+ BTA_MA_BMSG_LANG_ENGLISH, /* CDMA-SMS only */
+ BTA_MA_BMSG_LANG_FRENCH,
+ BTA_MA_BMSG_LANG_JAPANESE,
+ BTA_MA_BMSG_LANG_KOREAN,
+ BTA_MA_BMSG_LANG_CHINESE,
+ BTA_MA_BMSG_LANG_HEBREW
+};
+typedef UINT8 tBTA_MA_BMSG_LANGUAGE;
+
+
+enum
+{
+ BTA_MA_VCARD_VERSION_21=0,
+ BTA_MA_VCARD_VERSION_30
+};
+typedef UINT8 tBTA_MA_VCARD_VERSION;
+
+enum
+{
+ BTA_MA_VCARD_PROP_N,
+ BTA_MA_VCARD_PROP_FN,
+ BTA_MA_VCARD_PROP_TEL,
+ BTA_MA_VCARD_PROP_EMAIL,
+
+ BTA_MA_VCARD_PROP_MAX
+};
+typedef UINT8 tBTA_MA_VCARD_PROP;
+
+typedef struct
+{
+ char * p_param;
+ char * p_value;
+
+ /* link to the next property (if any) */
+ void * p_next;
+
+} tBTA_MA_VCARD_PROPERTY;
+
+typedef struct
+{
+ tBTA_MA_VCARD_VERSION version;
+
+ tBTA_MA_VCARD_PROPERTY * p_prop[BTA_MA_VCARD_PROP_MAX];
+
+ /* link to the next vCard (if any) */
+ void * p_next;
+
+} tBTA_MA_BMSG_VCARD;
+
+typedef struct BMSG_MESSAGE_struct
+{
+ char * p_text;
+
+ /* link to the next chunk of message text (if any) */
+ void * p_next;
+
+} tBTA_MA_BMSG_MESSAGE;
+
+typedef struct BMSG_CONTENT_struct
+{
+ /* this is the first bit of message text */
+ tBTA_MA_BMSG_MESSAGE * p_message;
+
+ /* this points to the last entered text -or-
+ ** it is the last that we returned back to
+ **
+ */
+ tBTA_MA_BMSG_MESSAGE * p_last;
+
+ /* link to the next chunk of content (if any) */
+ void * p_next;
+
+} tBTA_MA_BMSG_CONTENT;
+
+
+typedef struct
+{
+ /* Part ID */
+ UINT16 part_id;
+ BOOLEAN is_multipart;
+
+ /* Properties */
+ tBTA_MA_BMSG_ENCODING encoding;
+ tBTA_MA_BMSG_LANGUAGE language; /* optional */
+ tBTA_MA_CHARSET charset;
+ /* One or more body content */
+ tBTA_MA_BMSG_CONTENT * p_content;
+
+} tBTA_MA_BMSG_BODY;
+
+typedef struct BMSG_ENVELOPE_struct
+{
+ /* One or more Recipient (vCards) */
+ tBTA_MA_BMSG_VCARD * p_recip;
+
+ /* There will be either another envelope or the body */
+ void * p_next;
+ tBTA_MA_BMSG_BODY * p_body;
+
+} tBTA_MA_BMSG_ENVELOPE;
+
+typedef struct
+{
+ /* Property values */
+ BOOLEAN read_sts;
+ tBTA_MA_MSG_TYPE msg_type;
+ char * p_folder;
+
+ /* One or more Originator (vCards) */
+ tBTA_MA_BMSG_VCARD * p_orig;
+
+ /* Envelope */
+ tBTA_MA_BMSG_ENVELOPE * p_envelope;
+
+} tBTA_MA_BMSG;
+
+
+#endif
+
diff --git a/bta/include/bta_mse_api.h b/bta/include/bta_mse_api.h
new file mode 100644
index 0000000..742ea7a
--- /dev/null
+++ b/bta/include/bta_mse_api.h
@@ -0,0 +1,470 @@
+/*****************************************************************************
+**
+** Name: bta_mse_api.h
+**
+** Description: This is the public interface file for the Message Server Equipment
+** (MSE) subsystem of BTA, Broadcom's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_MSE_API_H
+#define BTA_MSE_API_H
+
+#include "bta_api.h"
+#include "bta_ma_def.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+/* Extra Debug Code */
+#ifndef BTA_MSE_DEBUG
+ #define BTA_MSE_DEBUG TRUE
+#endif
+
+/**************************
+** Common Definitions
+***************************/
+
+/* MSE callback function events */
+enum
+{
+ BTA_MSE_ENABLE_EVT = 0, /* MAS server is enabled. */
+ BTA_MSE_DISABLE_EVT,
+ BTA_MSE_ACCESS_EVT,
+ BTA_MSE_OPER_CMPL_EVT, /* MSE operation complete */
+ BTA_MSE_MA_OPEN_EVT,
+ BTA_MSE_MA_CLOSE_EVT,
+ BTA_MSE_SET_NOTIF_REG_EVT,
+ BTA_MSE_NOTIF_REG_EVT,
+ BTA_MSE_UPDATE_INBOX_EVT,
+ BTA_MSE_GET_MSG_IN_PROG_EVT,
+ BTA_MSE_PUSH_MSG_IN_PROG_EVT,
+ BTA_MSE_SEND_NOTIF_EVT,
+ BTA_MSE_MN_OPEN_EVT,
+ BTA_MSE_MN_CLOSE_EVT,
+ BTA_MSE_START_EVT,
+ BTA_MSE_STOP_EVT
+};
+typedef UINT8 tBTA_MSE_EVT;
+
+
+/* Structure associated with BTA_MSE_ENABLE_EVT
+ BTA_MSE_DISABLE_EVT
+*/
+typedef struct
+{
+ tBTA_MA_STATUS status;
+ UINT8 app_id;
+} tBTA_MSE_ENABLE_DISABLE;
+
+
+/*******************************************
+** Message Access Server Definitions
+********************************************/
+/* Access event operation types */
+#define BTA_MSE_OPER_NONE 0
+#define BTA_MSE_OPER_SETPATH 1
+#define BTA_MSE_OPER_GET_FOLDER_LIST 2
+#define BTA_MSE_OPER_GET_MSG_LIST 3
+#define BTA_MSE_OPER_GET_MSG 4
+#define BTA_MSE_OPER_SET_MSG_STATUS 5
+#define BTA_MSE_OPER_DEL_MSG 6
+#define BTA_MSE_OPER_PUSH_MSG 7
+#define BTA_MSE_OPER_NOTIF_REG 8
+#define BTA_MSE_OPER_UPDATE_INBOX 9
+
+typedef UINT8 tBTA_MSE_OPER;
+
+/* Structure associated with BTA_MSE_ACCESS_EVT */
+typedef struct
+{
+ tBTA_MA_SESS_HANDLE mas_session_id; /* MAS Session ID */
+ tBTA_MSE_OPER oper; /* operation */
+ char *p_path; /* full path name */
+ tBTM_BD_NAME dev_name; /* Name of device, "" if unknown */
+ BD_ADDR bd_addr; /* Address of device */
+ tBTA_MA_MSG_HANDLE handle;
+ BOOLEAN delete_sts;
+} tBTA_MSE_ACCESS;
+
+/* Structure associated with BTA_MSE_OPER_CMPL_EVT */
+typedef struct
+{
+ UINT32 obj_size; /* Total size of object 0 if unknow*/
+ tBTA_MA_SESS_HANDLE mas_session_id; /* MAS Session ID */
+ tBTA_MSE_OPER operation;
+ tBTA_MA_STATUS status;
+} tBTA_MSE_OPER_CMPL;
+
+
+/* Structure associated with BTA_MSE_MA_OPEN_EVT */
+typedef struct
+{
+ tBTA_MA_INST_ID mas_instance_id; /* MAS instance ID: one MAS
+ instance can support multiple
+ sessions */
+ tBTA_MA_SESS_HANDLE mas_session_id; /* MAS Session ID, all session based
+ operation will need to use this ID */
+ tBTM_BD_NAME dev_name; /* Name of device, "" if unknown */
+ BD_ADDR bd_addr; /* Address of device */
+
+} tBTA_MSE_MA_OPEN;
+
+/* Structure associated with BTA_MSE_MA_CLOSE_EVT */
+typedef struct
+{
+ tBTA_MA_STATUS status;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_INST_ID mas_instance_id;
+} tBTA_MSE_MA_CLOSE;
+
+/* Structure associated with BTA_MSE_MN_OPEN_EVT or
+ BTA_MSE_MN_CLOSE_EVT
+*/
+typedef struct
+{
+ tBTM_BD_NAME dev_name; /* Name of device, "" if unknown */
+ BD_ADDR bd_addr; /* Address of device */
+ tBTA_MA_INST_ID first_mas_instance_id; /* MN connection can be used for more
+ than one MasInstanceIDs.
+ first_mas_instance_id is the MasInstanceId of a
+ MAS service MCE first registers to receive the
+ message notification */
+} tBTA_MSE_MN_OPEN;
+
+typedef struct
+{
+ tBTM_BD_NAME dev_name; /* Name of device, "" if unknown */
+ BD_ADDR bd_addr; /* Address of device */
+} tBTA_MSE_MN_CLOSE;
+
+/* Update Inbox response types */
+enum
+{
+ BTA_MSE_UPDATE_INBOX_ALLOW = 0, /* Allow the update inbox */
+ BTA_MSE_UPDATE_INBOX_FORBID /* Disallow the update inbox */
+};
+typedef UINT8 tBTA_MSE_UPDATE_INBOX_TYPE;
+
+
+/* Set Notification Registration response types */
+enum
+{
+ BTA_MSE_SET_NOTIF_REG_ALLOW = 0, /* Allow the notification registration request*/
+ BTA_MSE_SET_NOTIF_REG_FORBID /* Disallow the notification registration request */
+};
+typedef UINT8 tBTA_MSE_SET_NOTIF_REG_TYPE;
+
+/* Structure associated with BTA_MSE_SEND_NOTIF_EVT */
+typedef struct
+{
+ tBTA_MA_STATUS status;
+ tBTA_MA_INST_ID mas_instance_id;
+ BD_ADDR bd_addr; /* remote MCE's BD address*/
+} tBTA_MSE_SEND_NOTIF;
+
+
+/* Structure associated with BTA_MSE_START_EVT or
+ BTA_MSE_STOP_EVT */
+typedef struct
+{
+ tBTA_MA_STATUS status;
+ UINT8 mas_instance_id;
+} tBTA_MSE_START_STOP;
+
+typedef struct
+{
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_INST_ID mas_instance_id;
+ tBTA_MA_NOTIF_STATUS notif_status;
+ BD_ADDR bd_addr; /* remote MCE's BD address*/
+}tBTA_MSE_SET_NOTIF_REG;
+
+typedef struct
+{
+ tBTA_MA_STATUS status;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_INST_ID mas_instance_id;
+ tBTA_MA_NOTIF_STATUS notif_status;
+ BD_ADDR bd_addr; /* remote MCE's BD address*/
+}tBTA_MSE_NOTIF_REG;
+
+
+/* Data associated with call back events */
+typedef union
+{
+ tBTA_MA_SESS_HANDLE mas_session_id; /* BTA_MSE_UPDATE_INBOX_EVT*/
+ tBTA_MSE_ENABLE_DISABLE enable;
+ tBTA_MSE_ENABLE_DISABLE disable;
+ tBTA_MSE_ACCESS access;
+ tBTA_MSE_SET_NOTIF_REG set_notif_reg;
+ tBTA_MSE_NOTIF_REG notif_reg;
+ tBTA_MSE_MN_OPEN mn_open;
+ tBTA_MSE_MN_CLOSE mn_close;
+ tBTA_MSE_MA_OPEN ma_open;
+ tBTA_MSE_MA_CLOSE ma_close;
+ tBTA_MSE_SEND_NOTIF send_notif;
+ tBTA_MA_IN_PROG get_msg_in_prog;
+ tBTA_MA_IN_PROG push_msg_in_prog;
+ tBTA_MSE_OPER_CMPL oper_cmpl;
+ tBTA_MSE_START_STOP start;
+ tBTA_MSE_START_STOP stop;
+} tBTA_MSE;
+
+/* MSE callback function */
+typedef void tBTA_MSE_CBACK(tBTA_MSE_EVT event, tBTA_MSE *p_data);
+
+
+/********************************************
+** Message Notification Client Definitions
+*********************************************/
+
+/* Send Notification function arguments definition */
+enum
+{
+ BTA_MSE_NOTIF_TYPE_NEW_MSG = 0,
+ BTA_MSE_NOTIF_TYPE_DELIVERY_SUCCESS,
+ BTA_MSE_NOTIF_TYPE_SENDING_SUCCESS,
+ BTA_MSE_NOTIF_TYPE_DELIVERY_FAILURE,
+ BTA_MSE_NOTIF_TYPE_SENDING_FAILURE,
+ BTA_MSE_NOTIF_TYPE_MEMORY_FULL,
+ BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE,
+ BTA_MSE_NOTIF_TYPE_MESSAGE_DELETED,
+ BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT,
+ BTA_MSE_NOTIF_TYPE_MAX
+};
+
+typedef UINT8 tBTA_MSE_NOTIF_TYPE;
+
+/* configuration related constant */
+
+
+
+/* MSE configuration data */
+#define BTA_MSE_NUM_INST 4
+#define BTA_MSE_NUM_SESS 4
+#define BTA_MSE_NUM_MN 7 /* i.e. up to 7 MCEs can be connected to the MSE */
+
+typedef struct
+{
+ INT32 obx_rsp_tout; /* maximum amount of time to wait for obx rsp */
+ UINT16 max_name_len; /* maximum folder name length */
+
+} tBTA_MSE_CFG;
+
+extern tBTA_MSE_CFG * p_bta_mse_cfg;
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************
+** API Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function BTA_MseEnable
+**
+** Description Enable the MSE subsystems. This function must be
+** called before any other functions in the MSE API are called.
+** When the enable operation is completed the callback function
+** will be called with an BTA_MSE_ENABLE_EVT event.
+**
+** Parameters p_cback - MSE event call back function
+** app_id - Application ID
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseEnable(tBTA_MSE_CBACK *p_cback, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_MseDisable
+**
+** Description Disable the MSE subsystem.
+**
+** Parameters
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseDisable(void);
+/*******************************************************************************
+**
+** Function BTA_MseStart
+**
+** Description Start a MA server on the MSE
+**
+**
+** Parameters mas_inst_id - MAS instance ID
+** sec_mask - Security Setting Mask
+** MSE always enables
+** (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
+** p_service_name - Pointer to service name
+** p_root_path - Pointer to root path
+** (one level above telecom)
+** sup_msg_type - supported message type(s)
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseStart( tBTA_MA_INST_ID mas_inst_id,
+ tBTA_SEC sec_mask, const char *p_service_name,
+ const char *p_root_path,
+ tBTA_MA_MSG_TYPE sup_msg_type);
+/*******************************************************************************
+**
+** Function BTA_MseStop
+**
+** Description Stop a MAS service on the MSE
+**
+** Parameters mas_instance_id - MAS Instance ID
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseStop (tBTA_MA_INST_ID mas_instance_id);
+
+/*******************************************************************************
+**
+** Function BTA_MseClose
+**
+** Description Close all MAS sessions on the specified MAS Instance ID
+**
+** Parameters mas_instance_id - MAS Inatance ID
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseClose(tBTA_MA_INST_ID mas_instance_id);
+
+/*******************************************************************************
+**
+** Function BTA_MseMaClose
+**
+** Description Close a MAS sessions on the specified BD address
+**
+** Parameters bd_addr - remote BD's address
+** mas_instance_id - MAS Inatance ID
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseMaClose(BD_ADDR bd_addr, tBTA_MA_INST_ID mas_instance_id);
+
+/*******************************************************************************
+**
+** Function BTA_MseMnClose
+**
+** Description Close a MN session
+**
+** Parameters bd_addr - remote BT's address
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseMnClose(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_MseAccessRsp
+**
+** Description Send a response for the access request
+**
+** Parameters mas_session_id - MAS session ID
+** oper - MAS operation type
+** access - Access is allowed or not
+** p_path - pointer to a path if if the operation
+** involves accessing a folder
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseAccessRsp(tBTA_MA_SESS_HANDLE mas_session_id, tBTA_MSE_OPER oper,
+ tBTA_MA_ACCESS_TYPE access, char *p_name);
+
+/*******************************************************************************
+**
+** Function BTA_MseUpdateInboxRsp
+**
+** Description Send a response for the update inbox request
+**
+**
+** Parameters mas_session_id - MAS session ID
+** update_rsp - update inbox is allowed or not
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseUpdateInboxRsp(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MSE_UPDATE_INBOX_TYPE update_rsp);
+
+/*******************************************************************************
+**
+** Function BTA_MseSetNotifRegRsp
+**
+** Description Send a response for the set notification registration
+**
+**
+** Parameters mas_session_id - MAS session ID
+** set_notif_reg_rsp - indicate whether the set notification
+** registration is allowed or not
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseSetNotifRegRsp(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MSE_SET_NOTIF_REG_TYPE set_notif_reg_rsp);
+
+/*******************************************************************************
+**
+** Function BTA_MseSendNotif
+**
+** Description Send a Message notification report to all MCEs registered with
+** the specified MAS instance ID
+**
+** Parameters mas_instance_id - MAS Instance ID
+** notif_type - message notification type
+** handle - message handle
+** p_folder - pointer to current folder
+** p_old_folder - pointer to older folder
+** msg_type - message type (E_MAIL, SMS_GSM, SMS_CDMA, MMS)
+** except_bd_addr - except to the MCE on this BD Address.
+** (Note: notification will be not sent to
+** this BD Addreess)
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseSendNotif(tBTA_MA_INST_ID mas_instance_id,
+ tBTA_MSE_NOTIF_TYPE notif_type,
+ tBTA_MA_MSG_HANDLE handle,
+ char * p_folder, char *p_old_folder,
+ tBTA_MA_MSG_TYPE msg_type,
+ BD_ADDR except_bd_addr);
+
+/*******************************************************************************
+**
+** Function BTA_MseMnAbort
+**
+** Description Abort the current OBEX multi-packt operation
+**
+** Parameters mas_instance_id - MAS Instance ID
+**
+** Returns void
+**
+*******************************************************************************/
+ BTA_API extern void BTA_MseMnAbort(tBTA_MA_INST_ID mas_instance_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_MSE_API_H */
diff --git a/bta/include/bta_mse_ci.h b/bta/include/bta_mse_ci.h
new file mode 100644
index 0000000..f366f16
--- /dev/null
+++ b/bta/include/bta_mse_ci.h
@@ -0,0 +1,146 @@
+/*****************************************************************************
+**
+** Name: bta_mse_ci.h
+**
+** Description: This is the interface file for the Message Server Equipment
+** (MSE) subsystem call-out functions.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_MSE_CI_H
+#define BTA_MSE_CI_H
+
+#include "bta_api.h"
+#include "bta_ma_def.h"
+#include "bta_mse_api.h"
+#include "bta_mse_co.h"
+
+/*******************************************************************************
+**
+** Function bta_mse_ci_get_folder_entry
+**
+** Description This function is called in response to the
+** bta_mse_co_get_folder_entry call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK if p_entry points to a valid entry.
+** BTA_MA_STATUS_EODIR if no more entries (p_entry is ignored).
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_ci_get_folder_entry(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 evt);
+/*******************************************************************************
+**
+** Function bta_mse_ci_get_msg_list_info
+**
+** Description This function is called in response to the
+** bta_mse_co_get_msg_list_info call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK 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_mse_ci_get_msg_list_info(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 evt);
+/*******************************************************************************
+**
+** Function bta_mse_ci_get_msg_list_entry
+**
+** Description This function is called in response to the
+** bta_mse_co_get_msg_list_entry call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK if p_entry points to a valid entry.
+** BTA_MA_STATUS_EODIR if no more entries (p_entry is ignored).
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_ci_get_msg_list_entry(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 evt);
+/*******************************************************************************
+**
+** Function bta_mse_ci_get_msg
+**
+** Description This function is called in response to the
+** bta_mse_co_get_msg call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK if p_msg points to a valid bmessage.
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** filled_buff_size - size of the filled buffer
+** multi_pkt_status - BTA_MA_MPKT_STATUS_MORE - need to get more packets
+** BTA_MA_MPKT_STATUS_LAST - last packet of the bMessage
+** frac_deliver_status - BTA_MA_FRAC_DELIVER_MORE - other fractions following
+** this bMessage
+** BTA_MA_FRAC_DELIVER_LAST - Last fraction
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_ci_get_msg(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 filled_buff_size,
+ tBTA_MA_MPKT_STATUS multi_pkt_status,
+ tBTA_MA_FRAC_DELIVER frac_deliver_status,
+ UINT16 evt);
+/*******************************************************************************
+**
+** Function bta_mse_ci_set_msg_delete_status
+**
+** Description This function is called in response to the
+** bta_mse_co_set_msg_delete_status call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** 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_mse_ci_set_msg_delete_status(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 evt);
+/*******************************************************************************
+**
+** Function bta_mse_ci_push_msg
+**
+** Description This function is called in response to the
+** bta_mse_co_push_msg call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK if the message upload is successful.
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** last_packet - last packet of a multi-packet message
+** handle - message handle for the uploaded message if
+** status is BTA_MA_OK and last_packet is TRUE
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_ci_push_msg(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ BOOLEAN last_packet,
+ tBTA_MA_MSG_HANDLE handle,
+ UINT16 evt);
+#endif /* BTA_MSE_CI_H */
+
+
+
+
diff --git a/bta/include/bta_mse_co.h b/bta/include/bta_mse_co.h
new file mode 100644
index 0000000..adc551f
--- /dev/null
+++ b/bta/include/bta_mse_co.h
@@ -0,0 +1,330 @@
+/*****************************************************************************
+**
+** Name: bta_mse_co.h
+**
+** Description: This is the interface file for the Message Server Equipment
+** (MSE) subsystem call-out functions.
+**
+** Copyright (c) 2009-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_MSE_CO_H
+#define BTA_MSE_CO_H
+
+#include "bta_api.h"
+#include "bta_ma_def.h"
+#include "bta_mse_api.h"
+
+/*****************************************************************************
+** Constants and Data Types
+*****************************************************************************/
+/**************************
+** Common Definitions
+***************************/
+
+
+/* Return structure type for a folder entry i.e. only folder level
+ information under the specified path and no file name */
+typedef struct
+{
+ UINT32 refdata; /* holder for OS specific data used to get next entry */
+ UINT32 filesize;
+ char *p_name; /* Contains the addr of memory to copy name into */
+ char crtime[BTA_FS_CTIME_LEN]; /* "yyyymmddTHHMMSSZ", or "" if none */
+ UINT8 mode; /* BTA_MSE_A_RDONLY and/or BTA_MSE_A_DIR */
+} tBTA_MSE_CO_FOLDER_ENTRY;
+
+
+#define BTA_MSE_CO_MAX_ADDR_LEN 256 /* See MAP spec 3.1.6 */
+#define BTA_MSE_CO_MAX_DATE_TIME 21 /* "YYYYMMDDTHHMMSS+hhmm" or "YYYYMMDDTHHMMSS" */
+
+enum
+{
+ BTA_MSE_CO_RCV_STATUS_COMPLETE = 0,
+ BTA_MSE_CO_RCV_STATUS_FRACTIONED,
+ BTA_MSE_CO_RCV_STATUS_NOTIFICATION,
+ BTA_MSE_CO_RCV_STATUS_MAX
+};
+
+typedef UINT8 tBTA_MSE_CO_RCV_STATUS;
+
+typedef struct
+{
+ UINT16 msg_list_size;
+ UINT8 mse_time_len;
+ char mse_time[BTA_FS_CTIME_LEN];
+ BOOLEAN new_msg;
+} tBTA_MSE_CO_MSG_LIST_INFO;
+
+typedef struct
+{
+ UINT32 refdata; /* holder for OS specific data used to get next msg entry */
+ tBTA_MA_ML_MASK parameter_mask;
+ UINT32 org_msg_size;
+ UINT32 attachment_size;
+ BOOLEAN text;
+ BOOLEAN high_priority;
+ BOOLEAN read;
+ BOOLEAN sent;
+ BOOLEAN is_protected;
+ tBTA_MA_MSG_HANDLE msg_handle;
+ tBTA_MA_MSG_TYPE type;
+ tBTA_MSE_CO_RCV_STATUS reception_status;
+ char subject[BTA_MSE_CO_MAX_ADDR_LEN];
+ char date_time[BTA_MSE_CO_MAX_DATE_TIME]; /* "YYYYMMDDTHHMMSS+hhmm", "YYYYMMDDTHHMMSS", or "" if none */
+ char sender_name[BTA_MSE_CO_MAX_ADDR_LEN];
+ char sender_addressing[BTA_MSE_CO_MAX_ADDR_LEN];
+ char recipient_name[BTA_MSE_CO_MAX_ADDR_LEN];
+ char recipient_addressing[BTA_MSE_CO_MAX_ADDR_LEN];
+ char replyto_addressing[BTA_MSE_CO_MAX_ADDR_LEN];
+} tBTA_MSE_CO_MSG_LIST_ENTRY;
+
+/*******************************************************************************
+**
+** Function bta_mse_co_update_inbox
+**
+** Description Update the inbox
+**
+** Parameters mas_session_id - MAS session ID
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which application
+** is the caller of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_co_update_inbox(tBTA_MA_SESS_HANDLE mas_session_id, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_mse_co_set_folder
+**
+** Description Set the current foldeer to the specified path
+**
+** Parameters mas_session_id - MAS session ID
+** p_path - points to the current folder path
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which application
+** is the caller of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_co_set_folder(tBTA_MA_SESS_HANDLE mas_session_id,
+ const char *p_path,
+ UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_mse_co_get_folder_entry
+**
+** Description This function is called to get a folder entry for the
+** specified path. The folder name should be filled
+** into the location specified by p_entry.
+**
+** Parameters mas_session_id - MAS session ID
+** p_path - points to the folder path to get the subfolder entry
+** (fully qualified path)
+** first_item - TRUE if first search, FALSE if next search
+** p_entry (input/output) - Points to the current entry data
+** 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 application
+** is the caller of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, the status is passed
+** in the bta_mse_ci_get_folder_entry() call-in function.
+** BTA_MA_STATUS_OK is returned when p_entry is valid,
+** BTA_MA_STATUS_EODIR is returned when no more entries [finished]
+** BTA_MA_STATUS_FAIL is returned if an error occurred
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_co_get_folder_entry(tBTA_MA_SESS_HANDLE mas_session_id, const char *p_path,
+ BOOLEAN first_item, tBTA_MSE_CO_FOLDER_ENTRY *p_entry,
+ UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_mse_co_get_msg_list_info
+**
+** Description This function is called to get a message list information for
+** the specified folder
+**
+** Parameters mas_session_id - MAS session ID
+** p_name - points to the current or child folder for getting the
+** message list information
+** (if *p_name == "" it means current folder)
+** filter_para - filter parameters for getting the message
+** list information
+** p_info(input/output) - Points to the message listing information
+** evt - event that be passed into the call-in function.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which application
+** is the caller of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, the status is passed
+** in the bta_mse_ci_get_msg_list_info() call-in function.
+** BTA_MA_STATUS_OK is returned when p_entry is valid
+** BTA_MA_STATUS_FAIL is returned if an error occurred
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_co_get_msg_list_info(tBTA_MA_SESS_HANDLE mas_session_id, const char *p_name,
+ tBTA_MA_MSG_LIST_FILTER_PARAM * p_filter_param,
+ tBTA_MSE_CO_MSG_LIST_INFO * p_info,
+ UINT16 evt, UINT8 app_id);
+/*******************************************************************************
+**
+** Function bta_mse_co_get_msg_list_entry
+**
+** Description This function is called to retrieve a message list entry for
+** the specified folder. The msg information should be filled by
+** application into the location specified by p_entry.
+**
+** Parameters mas_session_id - MAS session ID
+** p_name - points to the current or child folder for getting the
+** message list entry
+** (if *p_name == "" it means current folder)
+** filter_para - filter parameters for getting message list
+** first_item - TRUE if first get, FALSE if next msg
+** p_entry(input/output) - Points to current entry data
+** 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 application
+** is the caller of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, the status is passed
+** in the bta_mse_ci_get_msg_list_entry() call-in function.
+** BTA_MA_STATUS_OK is returned when p_entry is valid,
+** BTA_MA_STATUS_EODIR is returned when no more entries [finished]
+** BTA_MA_STATUS_FAIL is returned if an error occurred
+*******************************************************************************/
+BTA_API extern void bta_mse_co_get_msg_list_entry(tBTA_MA_SESS_HANDLE mas_session_id, const char *p_name,
+ tBTA_MA_MSG_LIST_FILTER_PARAM *p_filter_param,
+ BOOLEAN first_item, tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry,
+ UINT16 evt, UINT8 app_id);
+/*******************************************************************************
+**
+** Function bta_mse_co_get_msg
+**
+** Description This function is called to retrieve a msessage for the
+** specified message handle. The message will be filled by
+** application in bMessage format into the location
+** specified by p_buffer. The status and size of the filled
+** buffer are returned by bta_mse_ci_get_msg() call-in function
+**
+**
+** Parameters mas_session_id - MAS session ID
+** p_param - points to the parameters for the get message operation
+** first_get - TRUE first get FALSE subsequent get
+** buffer_size - size of the buffer pointed by p_buffer
+** p_buffer - points to the bMessage object storage location
+** evt - event that be passed into the call-in function.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which application
+** is the caller of the call-out function.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_co_get_msg(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_GET_MSG_PARAM *p_param,
+ BOOLEAN first_get,
+ UINT16 buffer_size,
+ UINT8 *p_buffer,
+ UINT16 evt,
+ UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_mse_co_set_msg_delete_status
+**
+** Description This function is called to set a message delete status
+**
+** Parameters mas_session_id - MAS session ID
+** handle - message handle
+** status value - 1- yes, 0 = No
+** evt_id - event that be passed into the call-in function.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which application
+** is the caller of the call-out function.
+**
+** Returns void
+**
+** Note: Upon completion of the request, the status is passed
+** in the bta_mse_ci_set_msg_delete_status() call-in function.
+** BTA_MA_STATUS_OK is returned when the delete operation is successful
+** BTA_MA_STATUS_FAIL is returned if an error occurred
+*******************************************************************************/
+BTA_API extern void bta_mse_co_set_msg_delete_status(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_MSG_HANDLE handle,
+ UINT8 status_value,
+ UINT16 evt_id,
+ UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_mse_co_set_msg_read_status
+**
+** Description This function is called to set a message read status
+**
+** Parameters mas_session_id - MAS session ID
+** handle - message handle
+** status value - 1- yes, 0 = No
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which application
+** is the caller of the call-out function.
+**
+** Returns BTA_MA_STATUS_OK - read status change is successful
+** BTA_MA_STATUS_FAIL
+*******************************************************************************/
+BTA_API extern tBTA_MA_STATUS bta_mse_co_set_msg_read_status(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_MSG_HANDLE handle,
+ UINT8 status_value,
+ UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function bta_mse_co_push_msg
+**
+** Description This function is called to upload a message to the
+** specified folder
+**
+** Parameters mas_session_id - MAS session ID
+** p_param - points to parameters for message upload
+** msg_len - length of the message to be uploaded
+** p_msg - points to the message to be uploaded
+** first_pkt - TRUE first push message packet
+** multi_pkt_status -
+** BTA_MA_MPKT_STATUS_MORE - need to get more packets
+** BTA_MA_MPKT_STATUS_LAST - last packet of
+** the bMessage to be uploaded
+** evt - event that be passed into the call-in function.
+** app_id - application ID specified in the enable functions.
+** It can be used to identify which application
+** is the caller of the call-out function.
+**
+** Returns void
+**
+** Note1: Upon completion of the request, the status is passed
+** in the bta_mse_ci_push_msg() call-in function.
+** BTA_MA_STATUS_OK is returned if the request is successful,
+** BTA_MA_STATUS_FAIL is returned if an error occurred
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_co_push_msg(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_PUSH_MSG_PARAM *p_param,
+ UINT16 msg_len,
+ UINT8 *p_msg,
+ BOOLEAN first_pkt,
+ tBTA_MA_MPKT_STATUS mpkt_status,
+ UINT16 evt,
+ UINT8 app_id);
+
+#endif /* BTA_MSE_CO_H */
diff --git a/bta/include/bta_op_api.h b/bta/include/bta_op_api.h
new file mode 100644
index 0000000..b2a624c
--- /dev/null
+++ b/bta/include/bta_op_api.h
@@ -0,0 +1,621 @@
+/*****************************************************************************
+**
+** Name: bta_op_api.h
+**
+** Description: This is the public interface file for the object push
+** (OP) client and server subsystem of BTA, Widcomm's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2003-2006, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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;
+
+/* Status */
+#define BTA_OP_OK 0 /* Operation successful. */
+#define BTA_OP_FAIL 1 /* Operation failed. */
+#define BTA_OP_MEM 2 /* Not enough memory to complete operation. */
+
+typedef UINT8 tBTA_OP_STATUS;
+
+/* vCal Object Type */
+#define BTA_OP_VCAL_EVENT 0 /* Object is an "Event" object. */
+#define BTA_OP_VCAL_TODO 1 /* Object is a "ToDo" object. */
+
+typedef UINT8 tBTA_OP_VCAL;
+
+/* vCard Property Names */
+#define BTA_OP_VCARD_ADR 1 /* Address. */
+#define BTA_OP_VCARD_EMAIL 2 /* Email address. */
+#define BTA_OP_VCARD_FN 3 /* Formatted name. */
+#define BTA_OP_VCARD_NOTE 4 /* Note. */
+#define BTA_OP_VCARD_NICKNAME 5 /* Nickname. */
+#define BTA_OP_VCARD_N 6 /* Name. */
+#define BTA_OP_VCARD_ORG 7 /* Organization. */
+#define BTA_OP_VCARD_TEL 8 /* Telephone number. */
+#define BTA_OP_VCARD_TITLE 9 /* Title. */
+#define BTA_OP_VCARD_URL 10 /* URL. */
+#define BTA_OP_VCARD_LUID 11 /* Locally Unique Identifier. */
+#define BTA_OP_VCARD_BDAY 12 /* Birthday. */
+#define BTA_OP_VCARD_PHOTO 13 /* Photo. */
+#define BTA_OP_VCARD_SOUND 14 /* Sound. */
+#define BTA_OP_VCARD_CALL 15 /* Call date-time */
+
+/* vCal Property Names */
+#define BTA_OP_VCAL_CATEGORIES 1 /* Categories of event. */
+#define BTA_OP_VCAL_COMPLETED 2 /* Time event is completed. */
+#define BTA_OP_VCAL_DESCRIPTION 3 /* Description of event. */
+#define BTA_OP_VCAL_DTEND 4 /* End date and time of event. */
+#define BTA_OP_VCAL_DTSTART 5 /* Start date and time of event. */
+#define BTA_OP_VCAL_DUE 6 /* Due date and time of event. */
+#define BTA_OP_VCAL_LOCATION 7 /* Location of event. */
+#define BTA_OP_VCAL_PRIORITY 8 /* Priority of event. */
+#define BTA_OP_VCAL_STATUS 9 /* Status of event. */
+#define BTA_OP_VCAL_SUMMARY 10 /* Summary of event. */
+#define BTA_OP_VCAL_LUID 11 /* Locally Unique Identifier. */
+
+/* vNote Property Names */
+#define BTA_OP_VNOTE_BODY 1 /* Message body text. */
+#define BTA_OP_VNOTE_LUID 2 /* Locally Unique Identifier. */
+
+/* Structure of the 32-bit parameters mask:
+**
+** + property-specific
+** +reserved | + character set
+** | | | + encoding
+** | | | |
+** 0000000000000000 00000000 00000 000
+*/
+
+/* Encoding Parameter */
+#define BTA_OP_ENC_QUOTED_PRINTABLE (1<<0) /* Quoted-Printable encoding. */
+#define BTA_OP_ENC_8BIT (2<<0) /* 8-bit encoding */
+#define BTA_OP_ENC_BINARY (3<<0) /* Binary encoding */
+// btla-specific ++
+#define BTA_OP_ENC_BASE64 (4<<0) /* base64 encoding */
+// btla-specific --
+
+/* Character Set Parameter */
+#define BTA_OP_CHAR_BIG5 (1<<3) /* Big5 character set. */
+#define BTA_OP_CHAR_EUC_JP (2<<3) /* EUC-JP character set. */
+#define BTA_OP_CHAR_EUC_KR (3<<3) /* EUC-KR character set. */
+#define BTA_OP_CHAR_GB2312 (4<<3) /* GB2312 character set. */
+#define BTA_OP_CHAR_ISO_2022_JP (5<<3) /* ISO-2022-JP character set. */
+#define BTA_OP_CHAR_ISO_8859_1 (6<<3) /* ISO-8859-1 character set. */
+#define BTA_OP_CHAR_ISO_8859_2 (7<<3) /* ISO-8859-2 character set. */
+#define BTA_OP_CHAR_ISO_8859_3 (8<<3) /* ISO-8859-3 character set. */
+#define BTA_OP_CHAR_ISO_8859_4 (9<<3) /* ISO-8859-4 character set. */
+#define BTA_OP_CHAR_ISO_8859_5 (10<<3) /* ISO-8859-5 character set. */
+#define BTA_OP_CHAR_ISO_8859_6 (11<<3) /* ISO-8859-6 character set. */
+#define BTA_OP_CHAR_ISO_8859_7 (12<<3) /* ISO-8859-7 character set. */
+#define BTA_OP_CHAR_ISO_8859_8 (13<<3) /* ISO-8859-8 character set. */
+#define BTA_OP_CHAR_KOI8_R (14<<3) /* KOI8-R character set. */
+#define BTA_OP_CHAR_SHIFT_JIS (15<<3) /* Shift_JIS character set. */
+#define BTA_OP_CHAR_UTF_8 (16<<3) /* UTF-8 character set. */
+
+/* Address Type Parameter */
+#define BTA_OP_ADR_DOM (1<<8) /* Domestic address. */
+#define BTA_OP_ADR_INTL (1<<9) /* International address. */
+#define BTA_OP_ADR_POSTAL (1<<10) /* Postal address. */
+#define BTA_OP_ADR_PARCEL (1<<11) /* Parcel post address. */
+#define BTA_OP_ADR_HOME (1<<12) /* Home address. */
+#define BTA_OP_ADR_WORK (1<<13) /* Work address. */
+
+/* EMAIL Type Parameter */
+#define BTA_OP_EMAIL_PREF (1<<8) /* Preferred email. */
+#define BTA_OP_EMAIL_INTERNET (1<<9) /* Internet email. */
+#define BTA_OP_EMAIL_X400 (1<<10) /* x400 emaill */
+
+/* Telephone Number Type Parameter */
+#define BTA_OP_TEL_PREF (1<<8) /* Preferred number. */
+#define BTA_OP_TEL_WORK (1<<9) /* Work number. */
+#define BTA_OP_TEL_HOME (1<<10) /* Home number. */
+#define BTA_OP_TEL_VOICE (1<<11) /* Voice number. */
+#define BTA_OP_TEL_FAX (1<<12) /* Fax number. */
+#define BTA_OP_TEL_MSG (1<<13) /* Message number. */
+#define BTA_OP_TEL_CELL (1<<14) /* Cell phone number. */
+#define BTA_OP_TEL_PAGER (1<<15) /* Pager number. */
+
+/* Photo Parameter */
+#define BTA_OP_PHOTO_VALUE_URI (1<<8) /* URI value */
+#define BTA_OP_PHOTO_VALUE_URL (1<<9) /* URL value */
+#define BTA_OP_PHOTO_TYPE_JPEG (1<<10) /* JPEG photo */
+#define BTA_OP_PHOTO_TYPE_GIF (1<<11) /* GIF photo */
+
+/* Sound Parameter */
+#define BTA_OP_SOUND_VALUE_URI (1<<8) /* URI value */
+#define BTA_OP_SOUND_VALUE_URL (1<<9) /* URL value */
+#define BTA_OP_SOUND_TYPE_BASIC (1<<10) /* BASIC sound */
+#define BTA_OP_SOUND_TYPE_WAVE (1<<11) /* WAVE sound */
+
+/* vCard filter mask */
+#define BTA_OP_FILTER_VERSION (1<<0) /* vCard Version */
+#define BTA_OP_FILTER_FN (1<<1) /* Formatted Name */
+#define BTA_OP_FILTER_N (1<<2) /* Structured Presentation of Name */
+#define BTA_OP_FILTER_PHOTO (1<<3) /* Associated Image or Photo */
+#define BTA_OP_FILTER_BDAY (1<<4) /* Birthday */
+#define BTA_OP_FILTER_ADR (1<<5) /* Delivery Address */
+#define BTA_OP_FILTER_LABEL (1<<6) /* Delivery */
+#define BTA_OP_FILTER_TEL (1<<7) /* Telephone Number */
+#define BTA_OP_FILTER_EMAIL (1<<8) /* Electronic Mail Address */
+#define BTA_OP_FILTER_MAILER (1<<9) /* Electronic Mail */
+#define BTA_OP_FILTER_TZ (1<<10) /* Time Zone */
+#define BTA_OP_FILTER_GEO (1<<11) /* Geographic Position */
+#define BTA_OP_FILTER_TITLE (1<<12) /* Job */
+#define BTA_OP_FILTER_ROLE (1<<13) /* Role within the Organization */
+#define BTA_OP_FILTER_LOGO (1<<14) /* Organization Logo */
+#define BTA_OP_FILTER_AGENT (1<<15) /* vCard of Person Representing */
+#define BTA_OP_FILTER_ORG (1<<16) /* Name of Organization */
+#define BTA_OP_FILTER_NOTE (1<<17) /* Comments */
+#define BTA_OP_FILTER_REV (1<<18) /* Revision */
+#define BTA_OP_FILTER_SOUND (1<<19) /* Pronunciation of Name */
+#define BTA_OP_FILTER_URL (1<<20) /* Uniform Resource Locator */
+#define BTA_OP_FILTER_UID (1<<21) /* Unique ID */
+#define BTA_OP_FILTER_KEY (1<<22) /* Public Encryption Key */
+#define BTA_OP_FILTER_NICKNAME (1<<23) /* Nickname */
+#define BTA_OP_FILTER_CATEGORIES (1<<24) /* Categories */
+#define BTA_OP_FILTER_PROID (1<<25) /* Product ID */
+#define BTA_OP_FILTER_CLASS (1<<26) /* Class Information */
+#define BTA_OP_FILTER_SORT_STRING (1<<27) /* String used for sorting operations */
+#define BTA_OP_FILTER_TIME_STAMP (1<<28) /* Time Stamp */
+#define BTA_OP_FILTER_ALL (0)
+
+/* This structure describes an object property, or individual item, inside an object. */
+typedef struct
+{
+ UINT8 *p_data; /* Pointer to property data. */
+ UINT32 parameters; /* Property parameters. */
+ UINT16 name; /* Property name. */
+ UINT16 len; /* Length of data. */
+ UINT8 *p_param; /* Pointer to the Parameters */
+ UINT16 param_len; /* Param Len */
+} tBTA_OP_PROP;
+
+
+/* Access response types */
+#define BTA_OP_ACCESS_ALLOW 0 /* Allow the requested operation */
+#define BTA_OP_ACCESS_FORBID 1 /* Disallow the requested operation */
+#define BTA_OP_ACCESS_NONSUP 2 /* Requested operation is not supported */
+
+typedef UINT8 tBTA_OP_ACCESS;
+
+/* Access event operation types */
+#define BTA_OP_OPER_PUSH 1
+#define BTA_OP_OPER_PULL 2
+
+typedef UINT8 tBTA_OP_OPER;
+
+
+/* Client callback function event */
+#define BTA_OPC_ENABLE_EVT 0 /* Object push client is enabled. */
+#define BTA_OPC_OPEN_EVT 1 /* Connection to peer is open. */
+#define BTA_OPC_PROGRESS_EVT 2 /* push/pull in progres */
+#define BTA_OPC_OBJECT_EVT 3 /* Object Pulled */
+#define BTA_OPC_OBJECT_PSHD_EVT 4 /* Object pushed */
+#define BTA_OPC_CLOSE_EVT 5 /* Connection to peer closed. */
+
+typedef UINT8 tBTA_OPC_EVT;
+
+/* Client callback function result */
+#define BTA_OPC_OK 0 /* Object push succeeded. */
+#define BTA_OPC_FAIL 1 /* Object push failed. */
+#define BTA_OPC_NOT_FOUND 2 /* Object not found. */
+#define BTA_OPC_NO_PERMISSION 3 /* Operation not authorized. */
+#define BTA_OPC_SRV_UNAVAIL 4 /* Service unavaliable */
+#define BTA_OPC_ON_BT 5 /* only used for BTA_OPC_MOVE_CH_EVT */
+#define BTA_OPC_RSP_FORBIDDEN 6 /* Operation forbidden */
+#define BTA_OPC_RSP_NOT_ACCEPTABLE 7 /* Operation not acceptable */
+
+typedef UINT8 tBTA_OPC_STATUS;
+
+/* Structure associated with BTA_OPC_OBJECT_EVT */
+typedef struct
+{
+ char *p_name; /* Object name. */
+ tBTA_OPC_STATUS status;
+} tBTA_OPC_OBJECT;
+
+typedef struct
+{
+ UINT32 obj_size; /* Total size of object (BTA_FS_LEN_UNKNOWN if unknown) */
+ UINT16 bytes; /* Number of bytes read or written since last progress event */
+ tBTA_OP_OPER operation; /* Is progress for Push or Pull */
+} tBTA_OPC_PROGRESS;
+
+/* Union of all client callback structures */
+typedef union
+{
+ tBTA_OPC_OBJECT object;
+ tBTA_OPC_PROGRESS prog;
+ tBTA_OPC_STATUS status;
+} tBTA_OPC;
+
+/* Client callback function */
+typedef void (tBTA_OPC_CBACK)(tBTA_OPC_EVT event, tBTA_OPC *p_data);
+
+/* Server callback function event */
+#define BTA_OPS_ENABLE_EVT 0 /* Object push server is enabled. */
+#define BTA_OPS_OPEN_EVT 1 /* Connection to peer is open. */
+#define BTA_OPS_PROGRESS_EVT 2 /* Object being sent or received. */
+#define BTA_OPS_OBJECT_EVT 3 /* Object has been received. */
+#define BTA_OPS_CLOSE_EVT 4 /* Connection to peer closed. */
+#define BTA_OPS_ACCESS_EVT 5 /* Request for access to push or pull object */
+
+typedef UINT8 tBTA_OPS_EVT;
+
+typedef UINT8 tBTA_OPS_STATUS;
+
+/* Structure associated with BTA_OPS_OBJECT_EVT */
+typedef struct
+{
+ char *p_name; /* Object name. */
+ tBTA_OP_FMT format; /* Object format. */
+} tBTA_OPS_OBJECT;
+
+typedef struct
+{
+ UINT32 obj_size; /* Total size of object (BTA_FS_LEN_UNKNOWN if unknown) */
+ UINT16 bytes; /* Number of bytes read or written since last progress event */
+ tBTA_OP_OPER operation; /* Is progress for Push or Pull */
+} tBTA_OPS_PROGRESS;
+
+typedef struct
+{
+ char *p_name; /* Object name */
+ char *p_type; /* Object type (NULL if not specified) */
+ UINT32 size; /* Object size */
+ tBTM_BD_NAME dev_name; /* Name of device, "" if unknown */
+ BD_ADDR bd_addr; /* Address of device */
+ tBTA_OP_OPER oper; /* Operation (push or pull) */
+ tBTA_OP_FMT format; /* Object format */
+} tBTA_OPS_ACCESS;
+
+/* Union of all server callback structures */
+typedef union
+{
+ tBTA_OPS_STATUS status;
+ tBTA_OPS_OBJECT object;
+ tBTA_OPS_PROGRESS prog;
+ tBTA_OPS_ACCESS access;
+ BD_ADDR bd_addr;
+} tBTA_OPS;
+
+/* Server callback function */
+typedef void (tBTA_OPS_CBACK)(tBTA_OPS_EVT event, tBTA_OPS *p_data);
+
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function BTA_OpcEnable
+**
+** Description Enable the object push client. This function must be
+** called before any other functions in the OP API are called.
+** When the enable operation is complete the callback function
+** will be called with a BTA_OPC_ENABLE_EVT.
+**
+** If single_op is FALSE, the connection stays open after
+** the operation finishes (until BTA_OpcClose is called).
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpcEnable(tBTA_SEC sec_mask, tBTA_OPC_CBACK *p_cback,
+ BOOLEAN single_op, BOOLEAN srm, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_OpcDisable
+**
+** Description Disable the object push client. If the client is currently
+** connected to a peer device the connection will be closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpcDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_OpcPush
+**
+** Description Push an object to a peer device. p_name must point to
+** a fully qualified path and file name.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpcPush(BD_ADDR bd_addr, tBTA_OP_FMT format, char *p_name);
+
+/*******************************************************************************
+**
+** Function BTA_OpcPullCard
+**
+** Description Pull default card from peer. p_path must point to a fully
+** qualified path specifying where to store the pulled card.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpcPullCard(BD_ADDR bd_addr, char *p_path);
+
+
+/*******************************************************************************
+**
+** Function BTA_OpcExchCard
+**
+** Description Exchange business cards with a peer device. p_send points to
+** a fully qualified path and file name of vcard to push.
+** p_recv_path points to a fully qualified path specifying
+** where to store the pulled card.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpcExchCard(BD_ADDR bd_addr, char *p_send,
+ char *p_recv_path);
+
+
+/*******************************************************************************
+**
+** Function BTA_OpcClose
+**
+** Description Close the current connection. This function is called if
+** the phone wishes to close the connection before the object
+** push is completed. In a typical connection this function
+** does not need to be called; the connection will be closed
+** automatically when the object push is complete.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpcClose(void);
+
+/*******************************************************************************
+**
+** Function BTA_OpsEnable
+**
+** Description Enable the object push server. This function must be
+** called before any other functions in the OPS API are called.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpsEnable(tBTA_SEC sec_mask, tBTA_OP_FMT_MASK formats,
+ char *p_service_name, tBTA_OPS_CBACK *p_cback,
+ BOOLEAN srm, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_OpsDisable
+**
+** Description Disable the object push server. If the server is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpsDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_OpsClose
+**
+** Description Close the current connection. This function is called if
+** the phone wishes to close the connection before the object
+** push is completed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpsClose(void);
+
+/*******************************************************************************
+**
+** Function BTA_OpsAccessRsp
+**
+** Description Sends a reply to an access request event (BTA_OPS_ACCESS_EVT).
+** This call MUST be made whenever the event occurs.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpsAccessRsp(tBTA_OP_OPER oper, tBTA_OP_ACCESS access,
+ char *p_name);
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildCard
+**
+** Description Build a vCard object. The input to this function is
+** requested format(2.1/3.0), an array of vCard properties
+** and a pointer to memory to store the card.
+** The output is a formatted vCard.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+BTA_API extern tBTA_OP_STATUS BTA_OpBuildCard(UINT8 *p_card, UINT16 *p_len,
+ tBTA_OP_FMT fmt,
+ tBTA_OP_PROP *p_prop,
+ UINT8 num_prop);
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildNote
+**
+** Description Build a vNote object. The input to this function is an
+** array of vNote properties and a pointer to memory to store
+** the card. The output is a formatted vNote.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+BTA_API extern tBTA_OP_STATUS BTA_OpBuildNote(UINT8 *p_note, UINT16 *p_len,
+ tBTA_OP_PROP *p_prop,
+ UINT8 num_prop);
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildCal
+**
+** Description Build a vCal 1.0 object. The input to this function is an
+** array of vCaalproperties and a pointer to memory to store
+** the card. The output is a formatted vCal.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+BTA_API extern tBTA_OP_STATUS BTA_OpBuildCal(UINT8 *p_cal, UINT16 *p_len,
+ tBTA_OP_PROP *p_prop,
+ UINT8 num_prop,
+ tBTA_OP_VCAL vcal_type);
+
+/*******************************************************************************
+**
+** Function BTA_OpParseCard
+**
+** Description Parse a vCard 2.1 object. The input to this function is
+** a pointer to vCard data. The output is an array of parsed
+** vCard properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+BTA_API extern tBTA_OP_STATUS BTA_OpParseCard(tBTA_OP_PROP *p_prop,
+ UINT8 *p_num_prop, UINT8 *p_card,
+ UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_OpGetCardProperty
+**
+** Description Get Card property value by name. The input to this function is
+** property name. The output is property value and len
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+**
+*******************************************************************************/
+BTA_API extern tBTA_OP_STATUS BTA_OpGetCardProperty(UINT8 *p_value, UINT16 *p_len, tBTA_OP_PROP *p_prop,
+ UINT8 num_prop, UINT8 *p_name);
+
+/*******************************************************************************
+**
+** Function BTA_OpParseNote
+**
+** Description Parse a vNote object. The input to this function is a
+** pointer to vNote data. The output is an array of parsed
+** vNote properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+BTA_API extern tBTA_OP_STATUS BTA_OpParseNote(tBTA_OP_PROP *p_prop,
+ UINT8 *p_num_prop,
+ UINT8 *p_note, UINT16 len);
+
+/*******************************************************************************
+**
+** Function BTA_OpParseCal
+**
+** Description Parse a vCal object. The input to this function is a
+** pointer to vCal data. The output is an array of parsed
+** vCal properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+BTA_API extern tBTA_OP_STATUS BTA_OpParseCal(tBTA_OP_PROP *p_prop,
+ UINT8 *p_num_prop, UINT8 *p_cal,
+ UINT16 len, tBTA_OP_VCAL *p_vcal_type);
+
+/*******************************************************************************
+**
+** Function BTA_OpSetCardPropFilterMask
+**
+** Description Set Property Filter Mask
+**
+**
+** Returns
+**
+*******************************************************************************/
+BTA_API extern void BTA_OpSetCardPropFilterMask(UINT32 mask);
+
+#ifdef __cplusplus
+}
+#endif
+
+#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..83fa40d
--- /dev/null
+++ b/bta/include/bta_pan_api.h
@@ -0,0 +1,187 @@
+/*****************************************************************************
+**
+** Name: bta_pan_api.h
+**
+** Description: This is the public interface file for the Personal
+** Area Networking (PAN) subsystem of BTA, Widcomm's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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_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..cd759d9
--- /dev/null
+++ b/bta/include/bta_pan_ci.h
@@ -0,0 +1,139 @@
+/*****************************************************************************
+**
+** Name: bta_pan_ci.h
+**
+** Description: This is the interface file for pan call-in
+** functions.
+**
+** Copyright (c) 2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..c8769f4
--- /dev/null
+++ b/bta/include/bta_pan_co.h
@@ -0,0 +1,189 @@
+/*****************************************************************************
+**
+** Name: bta_pan_co.h
+**
+** Description: This is the interface file for data gateway call-out
+** functions.
+**
+** Copyright (c) 2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..41198ff
--- /dev/null
+++ b/bta/include/bta_pbs_api.h
@@ -0,0 +1,298 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_api.h
+**
+** Description: This is the public interface file for the phone book access
+** (PB) server subsystem of BTA, Widcomm's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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 */
+
+enum
+{
+ BTA_PBS_VCF_FMT_21 = 0, /* vcard format 2.1 */
+ BTA_PBS_VCF_FMT_30 /* vcard format 3.0 */
+};
+typedef UINT8 tBTA_PBS_VCF_FMT;
+
+enum
+{
+ BTA_PBS_ORDER_INDEX = 0, /* Default. vCard handle */
+ BTA_PBS_ORDER_ALPHA_NUM, /* UTF8 name attribute, LastName then FirstName then MiddleName */
+ BTA_PBS_ORDER_PHONETIC /* UTF8 representation of the sound attribute */
+};
+typedef UINT8 tBTA_PBS_ORDER;
+
+enum
+{
+ BTA_PBS_ATTR_NAME = 0, /* name */
+ BTA_PBS_ATTR_NUMBER, /* number */
+ BTA_PBS_ATTR_SOUND, /* sound */
+ BTA_PBS_ATTR_MAX
+};
+typedef UINT8 tBTA_PBS_ATTR;
+
+#define BTA_PBS_FILTER_VERSION (1<<0) /* vCard Version */
+#define BTA_PBS_FILTER_FN (1<<1) /* Formatted Name */
+#define BTA_PBS_FILTER_N (1<<2) /* Structured Presentation of Name */
+#define BTA_PBS_FILTER_PHOTO (1<<3) /* Associated Image or Photo */
+#define BTA_PBS_FILTER_BDAY (1<<4) /* Birthday */
+#define BTA_PBS_FILTER_ADR (1<<5) /* Delivery Address */
+#define BTA_PBS_FILTER_LABEL (1<<6) /* Delivery */
+#define BTA_PBS_FILTER_TEL (1<<7) /* Telephone Number */
+#define BTA_PBS_FILTER_EMAIL (1<<8) /* Electronic Mail Address */
+#define BTA_PBS_FILTER_MAILER (1<<9) /* Electronic Mail */
+#define BTA_PBS_FILTER_TZ (1<<10) /* Time Zone */
+#define BTA_PBS_FILTER_GEO (1<<11) /* Geographic Position */
+#define BTA_PBS_FILTER_TITLE (1<<12) /* Job */
+#define BTA_PBS_FILTER_ROLE (1<<13) /* Role within the Organization */
+#define BTA_PBS_FILTER_LOGO (1<<14) /* Organization Logo */
+#define BTA_PBS_FILTER_AGENT (1<<15) /* vCard of Person Representing */
+#define BTA_PBS_FILTER_ORG (1<<16) /* Name of Organization */
+#define BTA_PBS_FILTER_NOTE (1<<17) /* Comments */
+#define BTA_PBS_FILTER_REV (1<<18) /* Revision */
+#define BTA_PBS_FILTER_SOUND (1<<19) /* Pronunciation of Name */
+#define BTA_PBS_FILTER_URL (1<<20) /* Uniform Resource Locator */
+#define BTA_PBS_FILTER_UID (1<<21) /* Unique ID */
+#define BTA_PBS_FILTER_KEY (1<<22) /* Public Encryption Key */
+#define BTA_PBS_FILTER_NICKNAME (1<<23) /* Nickname */
+#define BTA_PBS_FILTER_CATEGORIES (1<<24) /* Categories */
+#define BTA_PBS_FILTER_PROID (1<<25) /* Product ID */
+#define BTA_PBS_FILTER_CLASS (1<<26) /* Class Information */
+#define BTA_PBS_FILTER_SORT_STRING (1<<27) /* String used for sorting operations */
+#define BTA_PBS_FILTER_TIME_STAMP (1<<28) /* Time Stamp */
+#define BTA_PBS_FILTER_PROPRIETARY (1<<39) /* Indicates the usage of a proprietary filter */
+#define BTA_PBS_FILTER_ALL (0)
+
+typedef UINT32 tBTA_PBS_FILTER_MASK;
+
+/* Access response types */
+enum
+{
+ BTA_PBS_ACCESS_TYPE_ALLOW = 0, /* Allow the requested operation */
+ BTA_PBS_ACCESS_TYPE_FORBID, /* Disallow the requested operation */
+ BTA_PBS_ACCESS_TYPE_PRECONDITION /* Get vCard Entry operation only (object handle invalid) */
+};
+
+typedef UINT8 tBTA_PBS_ACCESS_TYPE;
+
+#define BTA_PBS_MAX_FILE_LEN 64
+#define BTA_PBS_MAX_CONTACT_NAME_LEN 128
+
+/* Obex application params passed to open callout */
+typedef struct
+{
+ tBTA_PBS_FILTER_MASK filter;
+ tBTA_PBS_VCF_FMT format;
+ UINT16 max_count;
+ UINT16 start_offset;
+} tBTA_PBS_PULLPB_APP_PARAMS;
+
+/* Obex application params passed to getvlist callout */
+typedef struct
+{
+ tBTA_PBS_ORDER order;
+ tBTA_PBS_ATTR attribute;
+ UINT8 p_value[64];
+ UINT16 value_len;
+ UINT16 max_count;
+ UINT16 start_offset;
+} tBTA_PBS_VCARDLIST_APP_PARAMS;
+
+/* VCard Listing structuture Returned by application*/
+typedef struct
+{
+ char handle[BTA_PBS_MAX_FILE_LEN]; /* Contains the vcf name */
+ char name[BTA_PBS_MAX_CONTACT_NAME_LEN]; /* Contains the contacted name of the vlist */
+} tBTA_PBS_VCARDLIST;
+
+/* Access event operation types */
+#define BTA_PBS_OPER_NONE 0
+#define BTA_PBS_OPER_PULL_PB 1
+#define BTA_PBS_OPER_SET_PB 2
+#define BTA_PBS_OPER_PULL_VCARD_LIST 3
+#define BTA_PBS_OPER_PULL_VCARD_ENTRY 4
+
+typedef UINT8 tBTA_PBS_OPER;
+
+/* Object type */
+#define BTA_PBS_NONE_OBJ 0
+#define BTA_PBS_PB_OBJ 1
+#define BTA_PBS_ICH_OBJ 2
+#define BTA_PBS_OCH_OBJ 3
+#define BTA_PBS_MCH_OBJ 4
+#define BTA_PBS_CCH_OBJ 5
+
+typedef UINT8 tBTA_PBS_OBJ_TYPE;
+
+
+/**************************
+** Server Definitions
+***************************/
+/* Extra Debug Code */
+#ifndef BTA_PBS_DEBUG
+#define BTA_PBS_DEBUG FALSE
+#endif
+
+#define BTA_PBS_OK 0
+#define BTA_PBS_FAIL 1
+typedef UINT8 tBTA_PBS_STATUS;
+
+/* Server callback function events */
+#define BTA_PBS_ENABLE_EVT 0 /* PB transfer server is enabled. */
+#define BTA_PBS_OPEN_EVT 1 /* Connection to peer is open. */
+#define BTA_PBS_CLOSE_EVT 2 /* Connection to peer closed. */
+#define BTA_PBS_AUTH_EVT 3 /* Request for Authentication key and realm */
+#define BTA_PBS_ACCESS_EVT 4 /* Request for access to put a file */
+#define BTA_PBS_OPER_CMPL_EVT 5 /* PB operation complete */
+
+typedef UINT8 tBTA_PBS_EVT;
+
+/* Structure associated with BTA_PBS_OPER_CMPL_EVT */
+typedef struct
+{
+ char *p_name; /* file or folder name. */
+ tBTA_PBS_OPER operation;
+ tBTA_PBS_STATUS status;
+} tBTA_PBS_OBJECT;
+
+typedef struct
+{
+ UINT8 *p_userid;
+ UINT8 userid_len;
+ BOOLEAN userid_required; /* TRUE if user ID is required in response (rechallanged) */
+} tBTA_PBS_AUTH;
+
+typedef struct
+{
+ char *p_name; /* file or directory name with fully qualified path */
+ tBTM_BD_NAME dev_name; /* Name of device, "" if unknown */
+ tBTA_PBS_OPER oper; /* operation */
+ BD_ADDR bd_addr; /* Address of device */
+} tBTA_PBS_ACCESS;
+
+typedef struct
+{
+ tBTM_BD_NAME dev_name; /* Name of device, "" if unknown */
+ BD_ADDR bd_addr; /* Address of device */
+} tBTA_PBS_OPEN;
+
+typedef union
+{
+ tBTA_PBS_AUTH auth;
+ tBTA_PBS_ACCESS access;
+ tBTA_PBS_OBJECT obj;
+ tBTA_PBS_OPEN open;
+} tBTA_PBS;
+
+/* Server callback function */
+typedef void tBTA_PBS_CBACK(tBTA_PBS_EVT event, tBTA_PBS *p_data);
+
+/**************************
+** Server Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function BTA_PbsEnable
+**
+** Description Enable the phone book access server. This function must be
+** called before any other functions in the PB Server API are called.
+** When the enable operation is complete the callback function
+** will be called with an BTA_PBS_ENABLE_EVT event.
+** Note: Pbs always enable (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PbsEnable(tBTA_SEC sec_mask, const char *p_service_name,
+ const char *p_root_path, BOOLEAN enable_authen,
+ UINT8 realm_len, UINT8 *p_realm,
+ tBTA_PBS_CBACK *p_cback, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function BTA_PbsDisable
+**
+** Description Disable the Phone book access server. If the server is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PbsDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_PbsAuthRsp
+**
+** Description Respond to obex client authenticate repond by sending back password to
+** BTA. Called in response to an BTA_PBS_AUTH_EVT event.
+** Used when "enable_authen" is set to TRUE in BTA_PbapsEnable().
+**
+** Note: If the "userid_required" is TRUE in the BTA_PBS_AUTH_EVT
+** event, then p_userid is required, otherwise it is optional.
+**
+** p_password must be less than BTA_PBS_MAX_AUTH_KEY_SIZE (16 bytes)
+** p_userid must be less than OBX_MAX_REALM_LEN (defined in target.h)
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PbsAuthRsp (char *p_password, char *p_userid);
+
+/*******************************************************************************
+**
+** Function BTA_PbsAccessRsp
+**
+** Description Sends a reply to an access request event (BTA_PBS_ACCESS_EVT).
+** This call MUST be made whenever the event occurs.
+**
+** Parameters oper - operation being accessed.
+** access - BTA_PBS_ACCESS_ALLOW or BTA_PBS_ACCESS_FORBID
+** p_name - path of file or directory to be accessed.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PbsAccessRsp(tBTA_PBS_OPER oper, tBTA_PBS_ACCESS_TYPE access,
+ char *p_name);
+
+/*******************************************************************************
+**
+** Function BTA_PbsClose
+**
+** Description Close the current connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PbsClose(void);
+#endif
diff --git a/bta/include/bta_pbs_ci.h b/bta/include/bta_pbs_ci.h
new file mode 100644
index 0000000..e44f960
--- /dev/null
+++ b/bta/include/bta_pbs_ci.h
@@ -0,0 +1,93 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_ci.h
+**
+** Description: This is the interface file for phone book access server
+** call-in functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_PBS_CI_H
+#define BTA_PBS_CI_H
+
+#include "bta_pbs_co.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_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_pbs_co_read() call-out function.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_pbs_ci_open call-in function.
+** num_bytes_read - number of bytes read into the buffer
+** specified in the read callout-function.
+** status - BTA_PBS_CO_OK if get buffer of data,
+** BTA_PBS_CO_FAIL if an error has occurred.
+** final - indicate whether it is the final data
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pbs_ci_read(int fd, UINT16 num_bytes_read,
+ tBTA_PBS_CO_STATUS status, BOOLEAN final);
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_open
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished opening a pb for reading.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_pbs_ci_open call-in function.
+** status - BTA_PBS_CO_OK if file was opened in mode specified
+** in the call-out function.
+** BTA_PBS_CO_EACCES if the file exists, but contains
+** the wrong access permissions.
+** BTA_PBS_CO_FAIL if any other error has occurred.
+** file_size - The total size of the file
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pbs_ci_open(int fd, tBTA_PBS_CO_STATUS status,
+ UINT32 file_size);
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_getvlist
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished reading a VCard list entry.
+**
+** Parameters
+** status - BTA_PBS_CO_OK if reading Vcard list entry
+** BTA_PBS_CO_FAIL if any other error has occurred.
+** final - whether it is the last entry
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pbs_ci_getvlist(tBTA_PBS_CO_STATUS status, BOOLEAN final);
+
+
+#endif
+
diff --git a/bta/include/bta_pbs_co.h b/bta/include/bta_pbs_co.h
new file mode 100644
index 0000000..76ec75a
--- /dev/null
+++ b/bta/include/bta_pbs_co.h
@@ -0,0 +1,160 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_co.h
+**
+** Description: This is the interface file for the phone book access server
+** call-out functions.
+**
+** Copyright (c) 2003-2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_PBS_CO_H
+#define BTA_PBS_CO_H
+
+#include "bta_api.h"
+#include "goep_fs.h"
+#include "bta_pbs_api.h"
+
+
+/*****************************************************************************
+** Constants and Data Types
+*****************************************************************************/
+/**************************
+** Common Definitions
+***************************/
+
+/* Status codes returned by call-out functions, or in call-in functions as status */
+#define BTA_PBS_CO_OK GOEP_OK
+#define BTA_PBS_CO_FAIL GOEP_FAIL /* Used to pass all other errors */
+#define BTA_PBS_CO_EACCES GOEP_EACCES
+#define BTA_PBS_CO_EOF GOEP_EOF
+#define BTA_PBS_CO_EODIR GOEP_EODIR
+
+typedef UINT16 tBTA_PBS_CO_STATUS;
+
+#define BTA_PBS_LEN_UNKNOWN GOEP_LEN_UNKNOWN
+#define BTA_PBS_INVALID_FD GOEP_INVALID_FD
+#define BTA_PBS_INVALID_APP_ID (0xFF) /* this app_id is reserved */
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+/**************************
+** Common Functions
+***************************/
+/*******************************************************************************
+**
+** Function bta_pbs_co_open
+**
+** Description This function is executed by BTA when a pb file is requested to be opened.
+** The phone book access profile server uses this function to open
+** a file for reading on two phone book access operations
+** (pull pb or pull pb entry)
+**
+** Parameters p_path - path and file name.
+** operation - BTA_PB_OPER_PULL_PB or BTA_PB_OPER_PULL_VCARD_ENTRY
+** p_app_params - obex application params
+**
+**
+** Returns void
+**
+** Note: Upon completion of the request
+** if successful, and an error code (tBTA_PBS_CO_STATUS)
+** are returned in the call-in function, bta_pbs_ci_open().
+**
+*******************************************************************************/
+BTA_API extern void bta_pbs_co_open(const char *p_path, tBTA_PBS_OPER operation, tBTA_PBS_PULLPB_APP_PARAMS *p_app_params);
+
+/*******************************************************************************
+**
+** Function bta_pbs_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.
+**
+**
+** Returns (tBTA_PBS_CO_STATUS) status of the call.
+** [BTA_PBS_CO_OK if successful],
+** [BTA_PBS_CO_FAIL if failed ]
+**
+*******************************************************************************/
+BTA_API extern tBTA_PBS_CO_STATUS bta_pbs_co_close(int fd);
+
+/*******************************************************************************
+**
+** Function bta_pbs_co_get_pbinfo
+**
+** Description This function is called by BTA to inquire about pb size and new missed calls.
+**
+** Parameters p_name: which type of phone book object Eg. telecom/pb.vcf, telecom/ich.vcf
+** operation: phone book operation type Eg. BTA_PBS_OPER_PULL_PB
+** obj_type: phone book repository type Eg. BTA_PBS_MCH_OBJ
+**
+** Returns pb_size - phone book size
+** new_missed_call - new missed calls
+* (tBTA_PBS_CO_STATUS) status of the call.
+** [BTA_PBS_CO_OK if successful],
+** [BTA_PBS_CO_FAIL if failed ]
+**
+*******************************************************************************/
+BTA_API extern tBTA_PBS_CO_STATUS bta_pbs_co_getpbinfo(tBTA_PBS_OPER operation, tBTA_PBS_OBJ_TYPE obj_type, UINT16 *pb_size, UINT16 *new_missed_call);
+
+/*******************************************************************************
+**
+** Function bta_pbs_co_read
+**
+** Description This function is called by BTA to read in data from the
+** previously opened pb file on the phone.
+** the application callin should fill in the PB object needed to be
+** send to the client
+**
+** Parameters fd - file descriptor of file to read from.
+** operation - BTA_PBS_OPER_PULL_PB or BTA_PBS_OPER_PULL_VCARD_ENTRY
+** p_buf - buffer to read the data into.
+** nbytes - number of bytes to read into the buffer.
+**
+**
+** Returns void
+**
+** Note: Upon completion of the request, bta_pbs_ci_read() is
+** called with the buffer of data, along with the number
+** of bytes read into the buffer, and a status.
+**
+*******************************************************************************/
+BTA_API extern void bta_pbs_co_read(int fd, tBTA_PBS_OPER operation, UINT8 *p_buf, UINT16 nbytes);
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_co_getvlist
+**
+** Description This function is called to retrieve a vcard list entry for the
+** specified path.
+** The first/next directory should be filled by application
+** into the location specified by p_entry.
+**
+** Parameters p_path - directory to search
+** p_app_params - Obex application params, NULL if first_item is FALSE
+** first_item - TRUE if first get, FALSE if next getvlist
+** (p_entry contains previous)
+** p_entry(input/output) - Points to prev entry data, the callout application need
+** to fill in with the next entry
+**
+**
+** Returns void
+**
+** Note: Upon completion of the request, bta_pbs_ci_getvlist() is
+** called with the a status and final flag.
+**
+**
+**
+*******************************************************************************/
+BTA_API extern void bta_pbs_co_getvlist(const char *p_path, tBTA_PBS_VCARDLIST_APP_PARAMS *p_app_params,
+ BOOLEAN first_item, tBTA_PBS_VCARDLIST *p_entry);
+
+
+#endif /* BTA_PBS_CO_H */
diff --git a/bta/include/bta_prm_api.h b/bta/include/bta_prm_api.h
new file mode 100644
index 0000000..434888f
--- /dev/null
+++ b/bta/include/bta_prm_api.h
@@ -0,0 +1,57 @@
+/*****************************************************************************
+**
+** Name: bta_prm_api.h
+**
+** Description: This is the public interface file for the patch ram
+** subsystem of BTA, Widcomm's
+** Bluetooth application layer for mobile phones.
+**
+** Copyright (c) 2003-2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_PRM_API_H
+#define BTA_PRM_API_H
+
+#include "bta_api.h"
+#include "bta_sys.h"
+
+/* callback function */
+typedef void (tBTA_PRM_CBACK) (tBTA_STATUS status);
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function BTA_PatchRam
+**
+** Description Patch Ram function
+**
+** Parameters p_cback - callback to indicate status of download operation.
+** p_name - path and file name of the patch file.
+** - if p_name is NULL, try to use patch data built into code.
+** fs_app_id - app_id used by bta file system callout functions
+** - to distinguish between applications which uses FS.
+** address - address of patch ram
+**
+**
+** Returns void
+**
+**
+*******************************************************************************/
+BTA_API extern void BTA_PatchRam(tBTA_PRM_CBACK *p_cback, const char *p_name,
+ UINT8 fs_app_id, UINT32 address);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
diff --git a/bta/include/bta_sc_api.h b/bta/include/bta_sc_api.h
new file mode 100644
index 0000000..90e673f
--- /dev/null
+++ b/bta/include/bta_sc_api.h
@@ -0,0 +1,193 @@
+/*****************************************************************************
+**
+** Name: bta_sc_api.c
+**
+** Description: This is the implementation of the API for the SIM
+** Card (SC) server subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_SC_API_H
+#define BTA_SC_API_H
+
+#include "bta_api.h"
+#include "sap_api.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+/* Status of SIM card (for BTA_ScCardStatus) */
+#define BTA_SC_CARD_UNKNOWN_ERROR SAP_CARD_UNKNOWN_ERROR /* Unknown problem with SIM card. */
+#define BTA_SC_CARD_RESET SAP_CARD_RESET /* SIM inserted and powered on prior to SIM Access Profile connection. */
+#define BTA_SC_CARD_NOT_ACCESSIBLE SAP_CARD_NOT_ACCESSIBLE /* SIM inserted, but not accessible. */
+#define BTA_SC_CARD_REMOVED SAP_CARD_REMOVED /* SIM not inserted, or has been removed. */
+#define BTA_SC_CARD_INSERTED SAP_CARD_INSERTED /* SIM inserted, but not powered on. Client needs to power on the SIM before using it. */
+#define BTA_SC_CARD_RECOVERED SAP_CARD_RECOVERED /* Previously not accessible card has been made accessible again, and is powered on by server. */
+typedef UINT8 tBTA_SC_CARD_STATUS;
+
+/* Flags describing Card Reader options (for reader_flags parameter of BTA_ScEnable) */
+#define BTA_SC_READER_FL_REMOVABLE 0x0001
+typedef UINT16 tBTA_SC_READER_FLAGS;
+
+/* Status of card reader (for BTA_ScReaderStatus) */
+#define BTA_SC_READER_STATUS_ATTACHED 0
+#define BTA_SC_READER_STATUS_REMOVED 1
+typedef UINT8 tBTA_SC_READER_STATUS;
+
+
+/* Disconnection type (for BTA_Disconnect) */
+#define BTA_SC_DISC_GRACEFUL SAP_DISCONNECT_GRACEFUL
+#define BTA_SC_DISC_IMMEDIATE SAP_DISCONNECT_IMMEDIATE
+typedef UINT8 tBTA_SC_DISCONNECT_TYPE;
+
+/* Server callback function events */
+#define BTA_SC_ENABLE_EVT 0 /* SIM Access server is enabled. */
+#define BTA_SC_OPEN_EVT 1 /* Connection to peer is open. */
+#define BTA_SC_CLOSE_EVT 2 /* Connection to peer closed. */
+// btla-specific ++
+#define BTA_SC_DISABLE_EVT 3 /* SIM Access server is disabled. */
+// btla-specific --
+typedef UINT8 tBTA_SC_EVT;
+
+
+/* Results codes for use with call-in functions */
+#define BTA_SC_RESULT_OK SAP_RESULT_OK /* Request processed correctly. */
+#define BTA_SC_RESULT_ERROR SAP_RESULT_ERROR /* Error - no reason specified. */
+#define BTA_SC_RESULT_CARD_NOT_ACCESSIBLE SAP_RESULT_CARD_NOT_ACCESSIBLE /* Error - card inserted but not accessible. */
+#define BTA_SC_RESULT_CARD_POWERED_OFF SAP_RESULT_CARD_POWERED_OFF /* Error - card is powered off. */
+#define BTA_SC_RESULT_CARD_REMOVED SAP_RESULT_CARD_REMOVED /* Error - card is not inserted. */
+#define BTA_SC_RESULT_CARD_ALREADY_ON SAP_RESULT_CARD_ALREADY_ON /* Error - card already turned on. */
+#define BTA_SC_RESULT_DATA_NOT_AVAILABLE SAP_RESULT_DATA_NOT_AVAILABLE /* Error - data not available. */
+/* Request codes for use with call-in functions */
+#define BTA_SC_REQUEST_APDU (BTA_SC_RESULT_OK + 10)
+typedef UINT8 tBTA_SC_RESULT;
+
+
+/* Results codes for sim reset */
+#define BTA_SC_RESET_RESULT_OK 0 /* Reset successful */
+#define BTA_SC_RESET_RESULT_ERROR 1 /* Reset failed */
+#define BTA_SC_RESET_RESULT_OK_ONGOING_CALL 2 /* Ongoing call (will reset after call is released) */
+typedef UINT8 tBTA_SC_RESET_RESULT;
+
+/**************************
+** Structure definitions
+***************************/
+/* Event data for BTA_SC_OPEN_EVT */
+typedef struct
+{
+ BD_ADDR bd_addr; /* Client bd address */
+} tBTA_SC_OPEN;
+
+
+/* Union of data types for BTA_SC callback function */
+typedef union
+{
+ tBTA_SC_OPEN open;
+} tBTA_SC;
+
+/* Server callback function */
+typedef void tBTA_SC_CBACK (tBTA_SC_EVT event, tBTA_SC *p_data);
+
+
+/*****************************************************************************
+** External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/*******************************************************************************
+**
+** Function BTA_ScEnable
+**
+** Description Enable the SIM Card server. This function must be
+** called before any other functions in the SC API are called.
+** When the enable operation is complete the callback function
+** will be called with a BTA_SC_ENABLE_EVT.
+**
+** Parameters
+** sec_mask Security options
+** p_service_name Service name for SDP record
+** reader_id SIM Card Reader ID (for TRANSFER_CARD_READER_STATUS requests)
+** reader_flags Flags describing card reader
+** msg_size_min Min message size for SIM APDU commands
+** msg_size_max Max message size for SIM APDU commands
+** p_cback Callback for BTA_SC event notification
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_ScEnable(tBTA_SEC sec_mask, const char *p_service_name,
+ UINT8 reader_id, tBTA_SC_READER_FLAGS reader_flags,
+ UINT16 msg_size_min, UINT16 msg_size_max,
+ tBTA_SC_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function BTA_ScDisable
+**
+** Description Disable the SIM Card server.
+**
+** Parameters none
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_ScDisable(void);
+
+/*******************************************************************************
+**
+** Function BTA_ScClose
+**
+** Description Close client connection.
+**
+** Parameters
+** type Type of disconnection desired (BTA_SC_DISC_GRACEFUL or
+** BTA_SC_DISC_IMMEDIATE)
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_ScClose(tBTA_SC_DISCONNECT_TYPE type);
+
+
+/*******************************************************************************
+**
+** Function BTA_ScCardStatus
+**
+** Description Notify client of change in SIM card status
+**
+** Parameters
+** status New status
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_ScCardStatus(tBTA_SC_CARD_STATUS status);
+
+
+/*******************************************************************************
+**
+** Function BTA_ScReaderStatus
+**
+** Description Notify client of change in SIM card reader status
+**
+** Parameters
+** status New status
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void BTA_ScReaderStatus(tBTA_SC_READER_STATUS status);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_SC_API_H */
diff --git a/bta/include/bta_sc_ci.h b/bta/include/bta_sc_ci.h
new file mode 100644
index 0000000..10b11e6
--- /dev/null
+++ b/bta/include/bta_sc_ci.h
@@ -0,0 +1,111 @@
+/*****************************************************************************
+**
+** Name: bta_sc_ci.h
+**
+** Description: This is the interface file for SIM Access server
+** call-in functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_SC_CI_H
+#define BTA_SC_CI_H
+
+#include "bta_sc_api.h"
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_sc_ci_apdu
+**
+** Description This function sends an event to SC to indicate the APDU request
+** has been completed or requested
+**
+** Parameters
+** result result of operation or request of operation
+** p_apdu response buffer for APDU command (if result=BTA_SC_RESULT_OK)
+** or request buffer for APDU command (if result=BTA_SC_REQUEST_APDU)
+** apdulen length of response or request buffer
+** is_apdu_7816 TRUE if format of apdu data is APDU7816
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_ci_apdu(tBTA_SC_RESULT result, UINT8 *p_apdu, UINT16 apdulen, BOOLEAN is_apdu_7816);
+
+/*******************************************************************************
+**
+** Function bta_sc_ci_atr
+**
+** Description This function sends an event to SC to indicate the ATR request
+** has been completed
+**
+** Parameters
+** result result of operation
+** p_atr response buffer for ATR request (if result=BTA_SC_RESULT_OK)
+** atrlen length of response buffer
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_ci_atr(tBTA_SC_RESULT result, UINT8 *p_atr, UINT16 atrlen);
+
+/*******************************************************************************
+**
+** Function bta_sc_ci_sim_on
+**
+** Description This function sends an event to SC to indicate the SIM_ON request
+** has been completed
+**
+** Parameters
+** result result of operation
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_ci_sim_on(tBTA_SC_RESULT result);
+
+/*******************************************************************************
+**
+** Function bta_sc_ci_sim_off
+**
+** Description This function sends an event to SC to indicate the SIM_OFF request
+** has been completed
+**
+** Parameters
+** result result of operation
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_ci_sim_off(tBTA_SC_RESULT result);
+
+/*******************************************************************************
+**
+** Function bta_sc_ci_sim_reset
+**
+** Description This function sends an event to SC to indicate the SIM_RESET request
+** has been completed
+**
+** Parameters
+** result result of operation
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_ci_sim_reset(tBTA_SC_RESET_RESULT result);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_SC_CI_H */
+
diff --git a/bta/include/bta_sc_co.h b/bta/include/bta_sc_co.h
new file mode 100644
index 0000000..a088823
--- /dev/null
+++ b/bta/include/bta_sc_co.h
@@ -0,0 +1,153 @@
+/*****************************************************************************
+**
+** Name: bta_sc_co.h
+**
+** Description: This is the interface file for the SIM access
+** server call-out functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_SC_CO_H
+#define BTA_SC_CO_H
+
+#include "bta_sc_api.h"
+
+/*****************************************************************************
+** Constants and Data Types
+*****************************************************************************/
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function bta_sc_co_sim_opem
+**
+** Description Called when client connection is opened, in case any special
+** handling or intialization of the SIM is required.
+**
+** Parameters
+** None.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_co_sim_open(void);
+
+/*******************************************************************************
+**
+** Function bta_sc_co_sim_close
+**
+** Description Called when client connection is closed.
+**
+** Parameters
+** None.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_co_sim_close(void);
+
+/*******************************************************************************
+**
+** Function bta_sc_co_sim_reset
+**
+** Description This function is called by BTA to reset the SIM card
+**
+** Once SIM has been turned reset, call bta_sc_ci_sim_reset().
+**
+** Parameters
+** None.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_co_sim_reset(void);
+
+/*******************************************************************************
+**
+** Function bta_sc_co_sim_off
+**
+** Description This function is called by BTA to turn the SIM card off
+**
+** Once SIM has been turned on, call bta_sc_ci_sim_on().
+**
+** Parameters
+** None.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_co_sim_off(void);
+
+/*******************************************************************************
+**
+** Function bta_sc_co_sim_on
+**
+** Description This function is called by BTA to turn the SIM card on
+**
+** Once SIM has been turned on, call bta_sc_ci_sim_on().
+**
+** Parameters
+** None.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_co_sim_on(void);
+
+/*******************************************************************************
+**
+** Function bta_sc_co_atr
+**
+** Description This function is called by BTA to retrieve ATR information
+** (operational requirements of the SIM, as described in
+** section 5.8 of GSM 11.11)
+**
+** Once the ATR information is retrieved, call bta_sc_ci_atr().
+**
+** Parameters
+** None.
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_co_atr(void);
+
+/*******************************************************************************
+**
+** Function bta_sc_co_apdu
+**
+** Description This function is called by BTA to to transfer APDU command
+** messages to the SIM. Generally used for selecting, storing
+** and retrieving data from the SIM.
+**
+** Once the command has been completed, call bta_sc_ci_apdu()
+** with the result.
+**
+** Parameters
+** p_apdu_req Pointer to the APDU message from the client. Format
+** is described in section 9 of GSM 11.11
+**
+** req_len Length of APDU message.
+**
+** rsp_maxlen Maximum length of response message allowed by client
+** (negotiated during CONNECT_REQ)
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_sc_co_apdu(UINT8 *p_apdu_req, UINT16 req_len, UINT16 rsp_maxlen, BOOLEAN is_apdu_7816);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_SC_CO_H */
diff --git a/bta/include/bta_sys_ci.h b/bta/include/bta_sys_ci.h
new file mode 100644
index 0000000..48cfab1
--- /dev/null
+++ b/bta/include/bta_sys_ci.h
@@ -0,0 +1,57 @@
+/*****************************************************************************
+**
+** Name: bta_sys_ci.h
+**
+** Description: This is the interface file for system call-in
+** functions.
+**
+** Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..2b82153
--- /dev/null
+++ b/bta/include/bta_sys_co.h
@@ -0,0 +1,47 @@
+/*****************************************************************************
+**
+** Name: bta_sys_co.h
+**
+** Description: This is the interface file for system callout
+** functions.
+**
+** Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..35082a0
--- /dev/null
+++ b/bta/include/ptim.h
@@ -0,0 +1,86 @@
+/*****************************************************************************
+**
+** Name: ptim.h
+**
+** Description: Protocol timer services.
+**
+** Copyright (c) 2003-2006, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..392d239
--- /dev/null
+++ b/bta/include/utl.h
@@ -0,0 +1,156 @@
+/*****************************************************************************
+**
+** Name: utl.h
+**
+** Description: Basic utility functions.
+**
+** Copyright (c) 2003-2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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/ma/bta_ma_api.c b/bta/ma/bta_ma_api.c
new file mode 100644
index 0000000..2157447
--- /dev/null
+++ b/bta/ma/bta_ma_api.c
@@ -0,0 +1,1203 @@
+/*****************************************************************************
+**
+** Name: bta_mse_api.c
+**
+** Description: This is the implementation of the common API for the Message
+** Acess Profile of BTA, Broadcom Corp's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2009-2011 Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED == TRUE)
+
+
+#include <string.h>
+#include "bta_ma_api.h"
+#include "bta_ma_util.h"
+#include "bta_ma_co.h"
+/*******************************************************************************
+**
+** Function BTA_MaBmsgCreate
+**
+** Description Create and initialize an instance of a tBTA_MA_BMSG structure.
+**
+** Parameters None
+**
+** Returns Pointer to a bMessage object, or NULL if this fails.
+**
+*******************************************************************************/
+tBTA_MA_BMSG * BTA_MaBmsgCreate(void)
+{
+ tBTA_MA_BMSG *p_msg = (tBTA_MA_BMSG *) bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG));
+
+ if ( p_msg )
+ {
+ memset(p_msg, 0, sizeof(tBTA_MA_BMSG));
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("BTA_MaBmsgCreate failed");
+ }
+
+ return(p_msg);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgFree
+**
+** Description Destroy (free) the contents of a tBTA_MA_BMSG structure.
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgFree(tBTA_MA_BMSG * p_msg)
+{
+ if ( p_msg )
+ {
+ /* free folder string */
+ bta_ma_bmsg_free(p_msg->p_folder);
+
+ /* free all the vCards */
+ bta_ma_bmsg_free_vcards(p_msg->p_orig);
+
+ /* free the envelopes */
+ bta_ma_bmsg_free_envelope(p_msg->p_envelope);
+
+ /* free b-message structure itself */
+ bta_ma_bmsg_free(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetReadSts
+**
+** Description Set the bmessage-readstatus-property value for the bMessage
+** object. If the 'read_sts' is TRUE then value will be "READ",
+** otherwise it is "UNREAD".
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+** read_sts - Read status TRUE- read FALSE - unread
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgSetReadSts(tBTA_MA_BMSG * p_msg, BOOLEAN read_sts)
+{
+ if ( p_msg )
+ p_msg->read_sts = read_sts;
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetReadSts
+**
+** Description Get the bmessage-readstatus-property value for the bMessage
+** object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Read status (TRUE/FALSE) for the specified bMessage.
+**
+*******************************************************************************/
+BOOLEAN BTA_MaBmsgGetReadSts(tBTA_MA_BMSG * p_msg)
+{
+ return( p_msg ? p_msg->read_sts : FALSE);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetMsgType
+**
+** Description Set the bmessage-type-property value for the bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+** msg_type - Message type
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgSetMsgType(tBTA_MA_BMSG * p_msg, tBTA_MA_MSG_TYPE msg_type)
+{
+ if ( p_msg )
+ p_msg->msg_type = msg_type;
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetMsgType
+**
+** Description Get the bmessage-type-property value for the specified
+** bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Message type
+**
+*******************************************************************************/
+tBTA_MA_MSG_TYPE BTA_MaBmsgGetMsgType(tBTA_MA_BMSG * p_msg)
+{
+ /* return 0 (for lack of a better value) */
+ return( p_msg ? p_msg->msg_type : 0);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetFolder
+**
+** Description Set the bmessage-folder-property value for the bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+** p_folder - Pointer to a folder path
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgSetFolder(tBTA_MA_BMSG *p_msg, char *p_folder)
+{
+ if ( p_msg && p_folder )
+ {
+ /* free any existing string */
+ if ( p_msg->p_folder )
+ bta_ma_bmsg_free(p_msg->p_folder);
+
+ /* allocate a new one */
+ p_msg->p_folder = (char *) bta_ma_bmsg_alloc(strlen(p_folder)+1);
+ if ( p_msg->p_folder )
+ BCM_STRNCPY_S(p_msg->p_folder, strlen(p_folder)+1, p_folder, strlen(p_folder)+1);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetFolder
+**
+** Description Get the bmessage-folder-property value for the specified
+** bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to folder path string, or NULL if it has not been set.
+**
+*******************************************************************************/
+char * BTA_MaBmsgGetFolder(tBTA_MA_BMSG * p_msg)
+{
+ return(p_msg ? (char *) p_msg->p_folder : NULL);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddOrigToBmsg
+**
+** Description Add an originator to the bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to a new vCard structure, or NULL if this function
+** fails.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_VCARD * BTA_MaBmsgAddOrigToBmsg(tBTA_MA_BMSG * p_msg)
+{
+ tBTA_MA_BMSG_VCARD * p_vcard = NULL;
+ tBTA_MA_BMSG_VCARD * p_last_vcard = NULL;
+
+ if ( p_msg )
+ {
+ p_vcard = (tBTA_MA_BMSG_VCARD *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_VCARD));
+ if ( p_vcard )
+ {
+ memset(p_vcard, 0, sizeof(tBTA_MA_BMSG_VCARD));
+ p_vcard->version = BTA_MA_VCARD_VERSION_21; /* default to 2.1 */
+
+ if ( p_msg->p_orig )
+ {
+ /* set pointer to the last entry in the list */
+ p_last_vcard = p_msg->p_orig;
+ while ( p_last_vcard->p_next )
+ p_last_vcard = (tBTA_MA_BMSG_VCARD *) p_last_vcard->p_next;
+
+ p_last_vcard->p_next = p_vcard;
+ }
+ else
+ p_msg->p_orig = p_vcard;
+ }
+ }
+
+ return(p_vcard);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetOrigFromBmsg
+**
+** Description Get the first originator vCard information from the specified
+** bMessage object
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to first 'originator vCard, or NULL not used.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetOrigFromBmsg(tBTA_MA_BMSG * p_msg)
+{
+ return(p_msg ? (tBTA_MA_BMSG_VCARD *) p_msg->p_orig : NULL);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddEnvToBmsg
+**
+** Description Add a new envelope to the bMessage object. This is the first
+** (top) level envelope. bMessage allows up to 3 levels of envelopes.
+** application should call BTA_MaBmsgAddEnvToEnv to add the 2nd
+** 3rd level enevelope.
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to a new envelope structure, or NULL if this
+** function fails.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgAddEnvToBmsg(tBTA_MA_BMSG * p_msg)
+{
+ tBTA_MA_BMSG_ENVELOPE * p_envelope = NULL;
+
+ if ( p_msg )
+ {
+ p_envelope = (tBTA_MA_BMSG_ENVELOPE *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_ENVELOPE));
+ if ( p_envelope )
+ {
+ memset(p_envelope, 0, sizeof(tBTA_MA_BMSG_ENVELOPE));
+ p_msg->p_envelope = p_envelope;
+ }
+ }
+
+ return( p_envelope );
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddEnvToEnv
+**
+** Description Add a child envelope to an existing envelope.
+**
+** Parameters p_envelope - Pointer to a parent envelope
+**
+** Returns Pointer to an envelope structure, or NULL if this
+** function fails.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgAddEnvToEnv(tBTA_MA_BMSG_ENVELOPE * p_envelope)
+{
+ tBTA_MA_BMSG_ENVELOPE * p_new_envelope = NULL;
+
+ if ( p_envelope )
+ {
+ p_new_envelope = (tBTA_MA_BMSG_ENVELOPE *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_ENVELOPE));
+ if ( p_new_envelope )
+ {
+ memset(p_new_envelope, 0, sizeof(tBTA_MA_BMSG_ENVELOPE));
+ p_envelope->p_next = p_new_envelope;
+ }
+ }
+
+ return( p_new_envelope );
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetEnv
+**
+** Description Get the pointer of the first level envelope.
+**
+** Parameters p_bmsg - Pointer to a bMessage object
+**
+** Returns Pointer to the first level envelope structure, or NULL if it
+** does not exist
+**
+*******************************************************************************/
+tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgGetEnv(tBTA_MA_BMSG * p_msg)
+{
+ return(p_msg ? (tBTA_MA_BMSG_ENVELOPE *) p_msg->p_envelope : NULL);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextEnv
+**
+** Description Get the child envelope of the specified parent envelope.
+**
+** Parameters p_env - Pointer to a parent envelope
+**
+** Returns Pointer to a child enevelope. NULL if the
+** envelope does not have a 'child' envelope.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_ENVELOPE * BTA_MaBmsgGetNextEnv(tBTA_MA_BMSG_ENVELOPE * p_env)
+{
+ return(p_env ? (tBTA_MA_BMSG_ENVELOPE *)p_env->p_next : NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddRecipToEnv
+**
+** Description Add recipient to the specified envelope.
+**
+** Parameters p_env - Pointer to a envelope
+**
+** Returns Pointer to a vCard structure. NULL if it
+** fails to allocate a vCard structure.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_VCARD * BTA_MaBmsgAddRecipToEnv(tBTA_MA_BMSG_ENVELOPE * p_env)
+{
+ tBTA_MA_BMSG_VCARD * p_vcard = NULL;
+ tBTA_MA_BMSG_VCARD * p_last_vcard = NULL;
+
+ if ( p_env )
+ {
+ p_vcard = (tBTA_MA_BMSG_VCARD *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_VCARD));
+ if ( p_vcard )
+ {
+ memset(p_vcard, 0, sizeof(tBTA_MA_BMSG_VCARD));
+ p_vcard->version = BTA_MA_VCARD_VERSION_21; /* default to 2.1 */
+
+ if ( p_env->p_recip )
+ {
+ /* set pointer to the last entry in the list */
+ p_last_vcard = p_env->p_recip;
+ while ( p_last_vcard->p_next )
+ p_last_vcard = (tBTA_MA_BMSG_VCARD *) p_last_vcard->p_next;
+
+ p_last_vcard->p_next = p_vcard;
+ }
+ else
+ p_env->p_recip = p_vcard;
+ }
+ }
+
+ return(p_vcard);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetRecipFromEnv
+**
+** Description Get the first recipient's vCard from the specified envelope.
+**
+** Parameters p_env - Pointer to a envelope
+**
+** Returns Pointer to the first recipient's vCard structure. NULL if it
+** has not be set.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetRecipFromEnv(tBTA_MA_BMSG_ENVELOPE * p_env)
+{
+ return(p_env ? p_env->p_recip : NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddBodyToEnv
+**
+** Description Add a message body to the specified envelope.
+**
+** Parameters p_env - Pointer to a envelope
+**
+** Returns Pointer to a message body structure.
+** NULL if it fails to allocate a message body structure.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_BODY * BTA_MaBmsgAddBodyToEnv(tBTA_MA_BMSG_ENVELOPE * p_env)
+{
+ tBTA_MA_BMSG_BODY * p_body = NULL;
+
+ if ( p_env )
+ {
+ /* free any existing body */
+ if ( p_env->p_body )
+ bta_ma_bmsg_free_body(p_env->p_body);
+
+ /* allocate a new one */
+ p_body = (tBTA_MA_BMSG_BODY *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_BODY));
+ if ( p_body )
+ {
+ memset(p_body, 0, sizeof(tBTA_MA_BMSG_BODY));
+ p_body->encoding = BTA_MA_BMSG_ENC_8BIT; /* default */
+ }
+
+ p_env->p_body = p_body;
+ }
+
+ return(p_body);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyFromEnv
+**
+** Description Get the message body pointer from the specified envelope.
+**
+** Parameters p_env - Pointer to a envelope
+**
+** Returns Pointer to a message body structure.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_BODY * BTA_MaBmsgGetBodyFromEnv(tBTA_MA_BMSG_ENVELOPE * p_env)
+{
+ return( p_env ? p_env->p_body : NULL);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetBodyEncoding
+**
+** Description Set the bmessage-body-encoding-property value for the bMessage
+** body.
+**
+** Parameters p_body - Pointer to a bMessage body
+** encoding - encoding scheme
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgSetBodyEncoding(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_BMSG_ENCODING encoding)
+{
+ if ( p_body )
+ p_body->encoding = encoding;
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyEncoding
+**
+** Description Get the bmessage-body-encoding-property value for the specified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Message encoding scheme
+**
+*******************************************************************************/
+tBTA_MA_BMSG_ENCODING BTA_MaBmsgGetBodyEncoding(tBTA_MA_BMSG_BODY * p_body)
+{
+ return( p_body ? p_body->encoding : BTA_MA_BMSG_ENC_8BIT );
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetBodyPartid
+**
+** Description Set the bmessage-body-part-ID value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+** part_id - Part ID (range: from 0 to 65535)
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgSetBodyPartid(tBTA_MA_BMSG_BODY * p_body, UINT16 part_id)
+{
+ if ( p_body )
+ {
+ p_body->part_id = part_id;
+ p_body->is_multipart = TRUE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyPartid
+**
+** Description Get the bmessage-body-part-ID value for the specified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns The value of the Part ID
+**
+*******************************************************************************/
+UINT16 BTA_MaBmsgGetBodyPartid(tBTA_MA_BMSG_BODY * p_body)
+{
+ return( p_body ? p_body->part_id : 0 );
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgIsBodyMultiPart
+**
+** Description Is this a multi-part body
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns TURE - if this is a multi-part body
+**
+*******************************************************************************/
+BOOLEAN BTA_MaBmsgIsBodyMultiPart(tBTA_MA_BMSG_BODY * p_body)
+{
+ return( p_body ? p_body->is_multipart : FALSE );
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetBodyCharset
+**
+** Description Set the bmessage-body-charset-property value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+** charset - Charset
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgSetBodyCharset(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_CHARSET charset)
+{
+ if ( p_body )
+ p_body->charset = charset;
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyCharset
+**
+** Description Get the bmessage-body-charset-property value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Charset
+**
+*******************************************************************************/
+tBTA_MA_CHARSET BTA_MaBmsgGetBodyCharset(tBTA_MA_BMSG_BODY * p_body)
+{
+ return( p_body ? p_body->charset : BTA_MA_CHARSET_UNKNOWN );
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetBodyLanguage
+**
+** Description Set the bmessage-body-language-property value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+** Language - the language of the message
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgSetBodyLanguage(tBTA_MA_BMSG_BODY * p_body, tBTA_MA_BMSG_LANGUAGE language)
+{
+ if ( p_body )
+ p_body->language = language;
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetBodyLanguage
+**
+** Description Get the bmessage-body-language-property value for the speicified
+** bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns the language of the message
+**
+*******************************************************************************/
+tBTA_MA_BMSG_LANGUAGE BTA_MaBmsgGetBodyLanguage(tBTA_MA_BMSG_BODY * p_body)
+{
+ return( p_body ? p_body->language : BTA_MA_BMSG_LANG_UNSPECIFIED );
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddContentToBody
+**
+** Description Add a message content to the speicified bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Pointer to a message content.
+** NULL if it fails to allocate a message content buffer
+**
+*******************************************************************************/
+tBTA_MA_BMSG_CONTENT * BTA_MaBmsgAddContentToBody(tBTA_MA_BMSG_BODY * p_body)
+{
+ tBTA_MA_BMSG_CONTENT * p_content = NULL;
+ tBTA_MA_BMSG_CONTENT * p_last_content = NULL;
+
+ if ( p_body )
+ {
+ p_content = (tBTA_MA_BMSG_CONTENT *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_CONTENT));
+ if ( p_content )
+ {
+ memset(p_content, 0, sizeof(tBTA_MA_BMSG_CONTENT));
+
+ if ( p_body->p_content )
+ {
+ /* set pointer to the last entry in the list */
+ p_last_content = p_body->p_content;
+ while ( p_last_content->p_next )
+ p_last_content = (tBTA_MA_BMSG_CONTENT *)p_last_content->p_next;
+
+ p_last_content->p_next = p_content;
+ }
+ else
+ p_body->p_content = p_content;
+ }
+ }
+
+ return(p_content);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetContentFromBody
+**
+** Description Get a message content from the speicified bMessage body.
+**
+** Parameters p_body - Pointer to a bMessage body
+**
+** Returns Pointer to a message content.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_CONTENT * BTA_MaBmsgGetContentFromBody(tBTA_MA_BMSG_BODY * p_body)
+{
+ return(p_body ? p_body->p_content : NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextContent
+**
+** Description Get the next message content from the speicified message content.
+**
+** Parameters p_content - Pointer to a message content
+**
+** Returns Pointer to a message content.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_CONTENT * BTA_MaBmsgGetNextContent(tBTA_MA_BMSG_CONTENT * p_content)
+{
+ return(p_content ? (tBTA_MA_BMSG_CONTENT *)p_content->p_next : NULL);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddMsgContent
+**
+** Description Add a text string to the speicified message content.
+**
+** Parameters p_content - Pointer to a message content
+** p_text - Pointer to a text string
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgAddMsgContent(tBTA_MA_BMSG_CONTENT * p_content, char * p_text)
+{
+ tBTA_MA_BMSG_MESSAGE * p_message;
+
+ if ( p_content )
+ {
+ p_message = (tBTA_MA_BMSG_MESSAGE *)bta_ma_bmsg_alloc(sizeof(tBTA_MA_BMSG_MESSAGE));
+ if ( p_message )
+ {
+ memset(p_message, 0, sizeof(tBTA_MA_BMSG_MESSAGE));
+
+ p_message->p_text = (char *)bta_ma_bmsg_alloc(strlen(p_text)+1);
+
+ if ( p_message->p_text )
+ {
+ BCM_STRNCPY_S(p_message->p_text, strlen(p_text)+1, p_text, strlen(p_text)+1);
+
+ /* if the content already points to a message,
+ ** then we tack it on the end of the message list.
+ */
+ if ( p_content->p_message && p_content->p_last )
+ p_content->p_last->p_next = p_message;
+ else
+ p_content->p_message = p_message;
+
+ /* keep track of the last message text we added */
+ p_content->p_last = p_message;
+ }
+ else
+ bta_ma_bmsg_free(p_message);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetMsgContent
+**
+** Description Get the first text string from the speicified message content.
+**
+** Parameters p_content - Pointer to a message content
+**
+** Returns Pointer to the first text string.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+char * BTA_MaBmsgGetMsgContent(tBTA_MA_BMSG_CONTENT * p_content)
+{
+ char * p_text = NULL;
+ if ( p_content && p_content->p_message )
+ {
+ /* reset 'last' pointer for when 'get_next' is called. */
+ p_content->p_last = p_content->p_message;
+
+ p_text = p_content->p_message->p_text;
+ }
+
+ return( p_text );
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetMsgContent
+**
+** Description Get the next text string from the speicified message content.
+**
+** Parameters p_content - Pointer to a message content
+**
+** Returns Pointer to the next text string.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+char * BTA_MaBmsgGetNextMsgContent(tBTA_MA_BMSG_CONTENT * p_content)
+{
+ char * p_text = NULL;
+
+ if ( p_content && p_content->p_last )
+ {
+ /* advance pointer */
+ p_content->p_last = ( tBTA_MA_BMSG_MESSAGE *)p_content->p_last->p_next;
+
+ if ( p_content->p_last )
+ p_text = p_content->p_last->p_text;
+ }
+
+ return( p_text );
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextVcard
+**
+** Description Get the next vCard from the speicified vCard.
+**
+** Parameters p_vcard - Pointer to a vCard
+**
+** Returns Pointer to the next vCard.
+** NULL if it has not been set.
+**
+*******************************************************************************/
+tBTA_MA_BMSG_VCARD * BTA_MaBmsgGetNextVcard(tBTA_MA_BMSG_VCARD * p_vcard)
+{
+ return(p_vcard ? (tBTA_MA_BMSG_VCARD *)p_vcard->p_next : NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function BTA_MaBmsgSetVcardVersion
+**
+** Description Set the vCard version for the speicified vCard.
+**
+** Parameters p_vcard - Pointer to a vCard
+** version - vcard version
+**
+** Returns None
+**
+*******************************************************************************/
+void BTA_MaBmsgSetVcardVersion(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_VERSION version)
+{
+ if ( p_vcard )
+ p_vcard->version = version;
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardVersion
+**
+** Description Get the vCard version from the speicified vCard.
+**
+** Parameters p_vcard - Pointer to a vCard
+**
+** Returns vCard version number
+**
+*******************************************************************************/
+tBTA_MA_VCARD_VERSION BTA_MaBmsgGetVcardVersion(tBTA_MA_BMSG_VCARD * p_vcard)
+{
+ return(p_vcard ? p_vcard->version : 0);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgAddVcardProp
+**
+** Description Add a property to the speicified vCard.
+**
+** Parameters p_vcard - Pointer to a vCard
+** prop - Indicate which vCard peoperty
+** p_value - Pointer to the vCard property value
+** p_param - Pointer to the vCard property parameter
+**
+** Returns Pointer to the vCard peoperty
+**
+*******************************************************************************/
+tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgAddVcardProp(tBTA_MA_BMSG_VCARD *p_vcard, tBTA_MA_VCARD_PROP prop, char *p_value, char *p_param)
+{
+ tBTA_MA_VCARD_PROPERTY * p_prop = NULL;
+ tBTA_MA_VCARD_PROPERTY * p_last_prop = NULL;
+
+ if ( p_vcard && prop < BTA_MA_VCARD_PROP_MAX )
+ {
+ p_prop = (tBTA_MA_VCARD_PROPERTY *) bta_ma_bmsg_alloc(sizeof(tBTA_MA_VCARD_PROPERTY));
+ if ( p_prop )
+ {
+ memset(p_prop, 0, sizeof(tBTA_MA_VCARD_PROPERTY));
+
+ /* Set the value (if given) */
+ if ( p_value )
+ {
+ p_prop->p_value = (char *)bta_ma_bmsg_alloc(strlen(p_value)+1);
+ if ( p_prop->p_value )
+ BCM_STRNCPY_S(p_prop->p_value, strlen(p_value)+1, p_value, strlen(p_value)+1);
+ }
+
+ /* Set the parameter (if given) */
+ if ( p_param )
+ {
+ p_prop->p_param = (char *)bta_ma_bmsg_alloc(strlen(p_param)+1);
+ if ( p_prop->p_param )
+ BCM_STRNCPY_S(p_prop->p_param, strlen(p_param)+1, p_param, strlen(p_param)+1);
+ }
+
+ /* There can be more than one of a property. So add this property to the end of the list. */
+ if ( p_vcard->p_prop[prop] == NULL )
+ p_vcard->p_prop[prop] = p_prop;
+ else
+ {
+ p_last_prop = p_vcard->p_prop[prop];
+ while ( p_last_prop->p_next )
+ p_last_prop = (tBTA_MA_VCARD_PROPERTY *)p_last_prop->p_next;
+
+ p_last_prop->p_next = p_prop;
+ }
+ }
+ }
+
+ return(p_prop);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardProp
+**
+** Description Get the vCard property from the speicified vCard peoperty enum.
+**
+** Parameters p_vcard - Pointer to a vCard
+** prop - Indicate which vCard peoperty
+**
+** Returns Pointer to the vCard peoperty.
+** NULL if the vCard peoperty does not exist
+**
+*******************************************************************************/
+tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgGetVcardProp(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_PROP prop)
+{
+ return( p_vcard && prop < BTA_MA_VCARD_PROP_MAX ? p_vcard->p_prop[prop] : NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetNextVcardProp
+**
+** Description Get the next vCard property from the speicified vCard peoperty.
+**
+** Parameters p_prop - Pointer to a vCard property
+**
+** Returns Pointer to the next vCard peoperty.
+** NULL if the next vCard peoperty does not exist
+**
+*******************************************************************************/
+tBTA_MA_VCARD_PROPERTY * BTA_MaBmsgGetNextVcardProp(tBTA_MA_VCARD_PROPERTY * p_prop)
+{
+ return(p_prop ? (tBTA_MA_VCARD_PROPERTY *)p_prop->p_next : NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardPropValue
+**
+** Description Get the vCard property value from the speicified vCard peoperty.
+**
+** Parameters p_prop - Pointer to a vCard property
+**
+** Returns Pointer to the vCard peoperty value.
+** NULL if the vCard peoperty value has not been set.
+**
+*******************************************************************************/
+char * BTA_MaBmsgGetVcardPropValue(tBTA_MA_VCARD_PROPERTY * p_prop)
+{
+ return(p_prop ? p_prop->p_value : NULL);
+}
+/*******************************************************************************
+**
+** Function BTA_MaBmsgGetVcardPropParam
+**
+** Description Get the vCard property parameter from the speicified vCard peoperty.
+**
+** Parameters p_prop - Pointer to a vCard property
+**
+** Returns Poiter to the vCard peoperty parameter.
+** NULL if the vCard peoperty parameter has not been set.
+**
+*******************************************************************************/
+char * BTA_MaBmsgGetVcardPropParam(tBTA_MA_VCARD_PROPERTY * p_prop)
+{
+ return(p_prop ? p_prop->p_param : NULL);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaBuildMapBmsgObj
+**
+** Description Builds a specification compliant bMessage object given a
+** generic bMessage internal structure.
+**
+** Parameters p_msg - pointer to bMessage object structure (input).
+** p_stream - Output stream.
+**
+** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not.
+**
+*******************************************************************************/
+tBTA_MA_STATUS BTA_MaBuildMapBmsgObj(tBTA_MA_BMSG * p_msg,
+ tBTA_MA_STREAM * p_stream)
+{
+ tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL;
+
+
+ if ( p_msg && p_stream )
+ {
+ bta_ma_stream_str(p_stream, "BEGIN:BMSG");
+ bta_ma_stream_str(p_stream, "\r\nVERSION:1.0");
+
+ /* Read Status */
+ bta_ma_stream_str(p_stream, "\r\nSTATUS:");
+ bta_ma_stream_str(p_stream, (BTA_MaBmsgGetReadSts(p_msg) ? "READ" : "UNREAD"));
+
+ /* Type */
+ bta_ma_stream_str(p_stream, "\r\nTYPE:");
+ bta_ma_stream_str(p_stream, bta_ma_msg_typ_to_string(BTA_MaBmsgGetMsgType(p_msg)));
+
+ /* Folder */
+ bta_ma_stream_str(p_stream, "\r\nFOLDER:");
+ bta_ma_stream_str(p_stream, BTA_MaBmsgGetFolder(p_msg));
+
+ /* Originator(s) */
+ bta_ma_stream_vcards(p_stream, BTA_MaBmsgGetOrigFromBmsg(p_msg));
+
+ /* Envelopes (nested) */
+ bta_ma_stream_envelopes(p_stream, BTA_MaBmsgGetEnv(p_msg));
+
+ bta_ma_stream_str(p_stream, "\r\nEND:BMSG\r\n");
+
+ /* if buffer overflowed then return failure */
+ status = bta_ma_stream_ok(p_stream)
+ ? BTA_MA_STATUS_OK
+ : BTA_MA_STATUS_FAIL;
+ }
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("BTA_MA_STATUS =%d (0-OK) BTA_MaBuildMapBmsgObj", status);
+#endif
+ return( status );
+}
+/*******************************************************************************
+**
+** Function bta_ma_parse_map_bmsg_obj
+**
+** Description Parses a bMessage object from a stream into a generic
+** bMessage internal structure.
+**
+** Parameters p_msg - pointer to bMessage object structure (output).
+** p_stream - Input stream.
+**
+** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not.
+**
+*******************************************************************************/
+tBTA_MA_STATUS BTA_MaParseMapBmsgObj(tBTA_MA_BMSG * p_msg,
+ tBTA_MA_STREAM * p_stream)
+{
+ char sz[BTA_MA_MAX_SIZE];
+ UINT32 prop_mask = 0;
+ tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL;
+ tBTA_MA_BMSG_VCARD * p_vcard = NULL;
+ tBTA_MA_BMSG_ENVELOPE * p_envelope = NULL;
+ tBTA_MA_MSG_TYPE msg_type = 0;
+
+ APPL_TRACE_EVENT0("BTA_MaParseMapBmsgObj");
+ if ( p_msg && p_stream )
+ {
+ /* Must start with BEGIN:MSG */
+ if ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE)
+ && (strcmp(sz, "BEGIN") == 0)
+ && bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE)
+ && (strcmp(sz, "BMSG") == 0) )
+ {
+ while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) )
+ {
+ /* VERSION */
+ if ( strcmp(sz, "VERSION") == 0 )
+ {
+ if ( bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE)
+ && (strcmp(sz, "1.0") == 0) )
+ {
+ prop_mask |= BTA_MA_PROP_VERSION;
+ }
+ else
+ break; /* incorrect VERSION */
+ }
+ else if ( strcmp(sz, "STATUS") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgSetReadSts(p_msg, (BOOLEAN) (strcmp(sz, "READ") == 0));
+ }
+ else if ( strcmp(sz, "TYPE") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ if ( bta_ma_str_to_msg_typ(sz, &msg_type) )
+ BTA_MaBmsgSetMsgType(p_msg, msg_type);
+
+ }
+ else if ( strcmp(sz, "FOLDER") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgSetFolder(p_msg, sz);
+ }
+ else if ( strcmp(sz, "BEGIN") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+
+ if ( strcmp(sz, "VCARD") == 0 )
+ {
+ p_vcard = BTA_MaBmsgAddOrigToBmsg(p_msg);
+ bta_ma_parse_vcard(p_vcard, p_stream);
+ }
+ else if ( strcmp(sz, "BENV") == 0 )
+ {
+ p_envelope = BTA_MaBmsgAddEnvToBmsg(p_msg);
+ bta_ma_parse_envelope(p_envelope, p_stream);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ma_parse_map_bmsg_obj - Invalid BEGIN: '%s'", sz);
+ }
+ }
+ else if ( strcmp(sz, "END") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ status = BTA_MA_STATUS_OK;
+ break;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ma_parse_map_bmsg_obj - Invalid tag: '%s'", sz);
+ }
+ }
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("BTA_MaParseMapBmsgObj status=%d(0-OK)", status);
+#endif
+ return( status );
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaInitMemStream
+**
+** Description Initializes a memory based stream
+**
+** Parameters p_stream - pointer to stream information.
+** p_buffer - pointer to buffer to be manipulated.
+** size - size of buffer pointed to by 'p_buffer'.
+**
+** Returns TRUE if stream is opened.
+**
+*******************************************************************************/
+BOOLEAN BTA_MaInitMemStream(tBTA_MA_STREAM * p_stream,
+ UINT8 * p_buffer,
+ UINT16 size)
+{
+ if ( !p_stream )
+ return(FALSE);
+
+ memset(p_stream, 0, sizeof(tBTA_MA_STREAM));
+
+ p_stream->type = STRM_TYPE_MEMORY;
+ p_stream->u.mem.p_buffer = p_stream->u.mem.p_next = p_buffer;
+ p_stream->u.mem.size = size;
+
+ return(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaInitFileStream
+**
+** Description Initializes a file stream
+**
+** Parameters p_stream - pointer to stream information.
+** p_path - Full pathname to file to use.
+** oflags - permissions and mode
+**
+** Returns TRUE if file stream is opened.
+**
+*******************************************************************************/
+BOOLEAN BTA_MaInitFileStream(tBTA_MA_STREAM * p_stream,
+ const char *p_path,
+ int oflags)
+{
+ if ( !p_stream )
+ {
+ APPL_TRACE_ERROR0("Invalid stream pointer");
+ return(FALSE);
+ }
+
+ memset(p_stream, 0, sizeof(tBTA_MA_STREAM));
+
+ p_stream->type = STRM_TYPE_FILE;
+
+ p_stream->u.file.fd = bta_ma_co_open(p_path, oflags);
+
+ if ( p_stream->u.file.fd == -1 )
+ {
+ APPL_TRACE_ERROR0("Unable to open file ");
+ p_stream->status = STRM_ERROR_FILE;
+ }
+
+ /* return TRUE if stream is OK */
+ return(p_stream->status == STRM_SUCCESS);
+}
+
+/*******************************************************************************
+**
+** Function BTA_MaCloseStream
+**
+** Description Close a stream (do any necessary clean-up).
+**
+** Parameters p_stream - pointer to stream information.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MaCloseStream(tBTA_MA_STREAM * p_stream)
+{
+ if ( p_stream->type == STRM_TYPE_FILE )
+ {
+ bta_ma_co_close(p_stream->u.file.fd);
+ p_stream->u.file.fd = BTA_FS_INVALID_FD;
+ }
+}
+#endif /* BTA_MSE_INCLUDED */
diff --git a/bta/ma/bta_ma_util.c b/bta/ma/bta_ma_util.c
new file mode 100644
index 0000000..6544e6a
--- /dev/null
+++ b/bta/ma/bta_ma_util.c
@@ -0,0 +1,1750 @@
+/*****************************************************************************
+**
+** Name: bta_ma_util.c
+**
+** Description: This is the implementation file for the Message Access
+** Profile (MAP) utility functions.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED)
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "bta_ma_api.h"
+#include "bta_ma_util.h"
+
+/*
+** Static constant data declarations
+*/
+/* Charset */static const char * bmsg_body_charset[] =
+{
+ "native", /* BMSG_CHARSET_NATIVE (native) */
+ "UTF-8" /* BMSG_CHARSET_UTF-8 (UTF-8) */
+};
+
+static const int num_bmsg_body_charset = sizeof(bmsg_body_charset) / sizeof(char*);
+
+
+/* vCard property names (the order is dicated by the tBTA_MA_BMSG_VCARD_PROP enumeration in bmsg_cnt.h) */
+static const char * vcard_prop_name[] =
+{
+ "N", /* VCARD_PROP_N */
+ "FN", /* VCARD_PROP_FN */
+ "TEL", /* VCARD_PROP_TEL */
+ "EMAIL" /* VCARD_PROP_EMAIL */
+};
+
+/* bMessage encoding names (the order is dictated by the tBTA_MA_BMSG_ENCODING enumeration in bmsg_cnt.h) */
+static const char * bmsg_body_encoding[] =
+{
+ "8BIT", /* BMSG_ENC_8BIT (8-Bit-Clean encoding) */
+ "G-7BIT", /* BMSG_ENC_G7BIT (GSM 7 bit Default Alphabet) */
+ "G-7BITEXT", /* BMSG_ENC_G7BITEXT (GSM 7 bit Alphabet with national language extension) */
+ "G-UCS2" , /* BMSG_ENC_GUCS2 */
+ "G-8BIT", /* BMSG_ENC_G8BIT */
+ "C-8BIT", /* BMSG_ENC_C8BIT (Octet, unspecified) */
+ "C-EPM", /* BMSG_ENC_CEPM (Extended Protocol Message) */
+ "C-7ASCII", /* BMSG_ENC_C7ASCII (7-bit ASCII) */
+ "C-IA5", /* BMSG_ENC_CIA5 (IA5) */
+ "C-UNICODE", /* BMSG_ENC_CUNICODE (UNICODE) */
+ "C-SJIS", /* BMSG_ENC_CSJIS (Shift-JIS) */
+ "C-KOREAN", /* BMSG_ENC_CKOREAN (Korean) */
+ "C-LATINHEB", /* BMSG_ENC_CLATINHEB (Latin/Hebrew) */
+ "C-LATIN" /* BMSG_ENC_CLATIN (Latin) */
+};
+
+static const int num_bmsg_body_encoding = sizeof(bmsg_body_encoding) / sizeof(char*);
+
+static const char * bmsg_body_language[] =
+{
+ "", /* BMSG_LANG_UNSPECIFIED (not provided in bBody */
+ "UNKNOWN", /* BMSG_LANG_UNKNOWN */
+ "SPANISH", /* BMSG_LANG_SPANISH */
+ "TURKISH", /* BMSG_LANG_TURKISH */
+ "PORTUGUESE", /* BMSG_LANG_PORTUGUESE */
+ "ENGLISH", /* BMSG_LANG_ENGLISH */
+ "FRENCH", /* BMSG_LANG_FRENCH */
+ "JAPANESE", /* BMSG_LANG_JAPANESE */
+ "KOREAN", /* BMSG_LANG_KOREAN */
+ "CHINESE", /* BMSG_LANG_CHINESE */
+ "HEBREW" /* BMSG_LANG_HEBREW */
+};
+
+static const int num_bmsg_body_language = sizeof(bmsg_body_language) / sizeof(char*);
+
+#include "bta_ma_co.h"
+
+#define BTA_MSE_NOTIF_TYPE_NEW_MSG_STR "NewMessage"
+#define BTA_MSE_NOTIF_TYPE_DELIVERY_SUCCESS_STR "DeliverySuccess"
+#define BTA_MSE_NOTIF_TYPE_SENDING_SUCCESS_STR "SendingSuccess"
+#define BTA_MSE_NOTIF_TYPE_DELIVERY_FAILURE_STR "DeliveryFailure"
+#define BTA_MSE_NOTIF_TYPE_SENDING_FAILURE_STR "SendingFailure"
+#define BTA_MSE_NOTIF_TYPE_MEMORY_FULL_STR "MemoryFull"
+#define BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE_STR "MemoryAvailable"
+#define BTA_MSE_NOTIF_TYPE_MESSAGE_DELETED_STR "MessageDeleted"
+#define BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT_STR "MessageShift"
+
+#define BTA_MSE_MSG_TYPE_EMAIL "EMAIL"
+#define BTA_MSE_MSG_TYPE_SMS_GSM "SMS_GSM"
+#define BTA_MSE_MSG_TYPE_SMS_CDMA "SMS_CDMA"
+#define BTA_MSE_MSG_TYPE_MMS "MMS"
+
+#define BTA_MSE_RCV_STATUS_COMPLETE "complete"
+#define BTA_MSE_RCV_STATUS_FRACTIONED "fractioned"
+#define BTA_MSE_RCV_STATUS_NOTIFICATION "notification"
+
+#define BTA_MSE_BOOLEAN_YES "yes"
+#define BTA_MSE_BOOLEAN_NO "no"
+
+/*******************************************************************************
+**
+** Function bta_ma_evt_typ_to_string
+**
+** Description Utility function to return a pointer to a string holding
+** the notifiction "type" for the MAP-Event-Report object.
+**
+** Parameters notif_type - Notification type
+**
+** Returns Pointer to static string representing notification type.
+**
+*******************************************************************************/
+
+const char * bta_ma_evt_typ_to_string(tBTA_MSE_NOTIF_TYPE notif_type)
+{
+ switch (notif_type)
+ {
+ case BTA_MSE_NOTIF_TYPE_NEW_MSG:
+ return(BTA_MSE_NOTIF_TYPE_NEW_MSG_STR);
+ case BTA_MSE_NOTIF_TYPE_DELIVERY_SUCCESS:
+ return(BTA_MSE_NOTIF_TYPE_DELIVERY_SUCCESS_STR);
+ case BTA_MSE_NOTIF_TYPE_SENDING_SUCCESS:
+ return(BTA_MSE_NOTIF_TYPE_SENDING_SUCCESS_STR);
+ case BTA_MSE_NOTIF_TYPE_DELIVERY_FAILURE:
+ return(BTA_MSE_NOTIF_TYPE_DELIVERY_FAILURE_STR);
+ case BTA_MSE_NOTIF_TYPE_SENDING_FAILURE:
+ return(BTA_MSE_NOTIF_TYPE_SENDING_FAILURE_STR);
+ case BTA_MSE_NOTIF_TYPE_MEMORY_FULL:
+ return(BTA_MSE_NOTIF_TYPE_MEMORY_FULL_STR);
+ case BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE:
+ return(BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE_STR);
+ case BTA_MSE_NOTIF_TYPE_MESSAGE_DELETED:
+ return(BTA_MSE_NOTIF_TYPE_MESSAGE_DELETED_STR);
+ case BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT:
+ return(BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT_STR);
+ }
+
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_msg_typ_to_string
+**
+** Description Utility function to return a pointer to a string holding
+** the "msg_type" for the MAP-Event-Report object or or the
+** the type for the MAP-msg-listing object
+**
+** Parameters msg_typ - Message type
+**
+** Returns Pointer to static string representing message type.
+**
+*******************************************************************************/
+
+const char * bta_ma_msg_typ_to_string(tBTA_MA_MSG_TYPE msg_typ)
+{
+ switch (msg_typ)
+ {
+ case BTA_MA_MSG_TYPE_EMAIL: return(BTA_MSE_MSG_TYPE_EMAIL);
+ case BTA_MA_MSG_TYPE_SMS_GSM: return(BTA_MSE_MSG_TYPE_SMS_GSM);
+ case BTA_MA_MSG_TYPE_SMS_CDMA: return(BTA_MSE_MSG_TYPE_SMS_CDMA);
+ case BTA_MA_MSG_TYPE_MMS: return(BTA_MSE_MSG_TYPE_MMS);
+ }
+
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_rcv_status_to_string
+**
+** Description Utility function to return a pointer to a string holding
+** the "reception_status" for the MAP-msg-listing object
+**
+** Parameters rcv_status - Reception status
+**
+** Returns Pointer to static string representing message type.
+**
+*******************************************************************************/
+const char * bta_ma_rcv_status_to_string(tBTA_MSE_CO_RCV_STATUS rcv_status)
+{
+ switch (rcv_status)
+ {
+ case BTA_MSE_CO_RCV_STATUS_COMPLETE:
+ return(BTA_MSE_RCV_STATUS_COMPLETE);
+ case BTA_MSE_CO_RCV_STATUS_FRACTIONED:
+ return(BTA_MSE_RCV_STATUS_FRACTIONED);
+ case BTA_MSE_CO_RCV_STATUS_NOTIFICATION:
+ return(BTA_MSE_RCV_STATUS_NOTIFICATION);
+ }
+
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_str
+**
+** Description Input a string into the stream.
+**
+** Parameters p_stream - pointer to stream information.
+** p_str - pointer to string to be put in the buffer. Only the
+** string characters, and not the NULL, are put into the
+** buffer.
+**
+** Returns TRUE if the string was successfully added into the stream.
+**
+*******************************************************************************/
+BOOLEAN bta_ma_stream_str(tBTA_MA_STREAM * p_stream, const char * p_str)
+{
+ UINT16 buf_size;
+ UINT16 str_size;
+ UINT16 size = 0;
+
+ /* ensure stream and string are not NULL */
+ if ( !p_str || !p_stream )
+ return(FALSE);
+
+ /* get length of string */
+ str_size = strlen(p_str);
+
+ switch ( p_stream->type )
+ {
+ case STRM_TYPE_MEMORY:
+ /* ensure buffer is not full */
+ if ( p_stream->status == STRM_SUCCESS )
+ {
+ /* get amount of size left in buffer */
+ buf_size = p_stream->u.mem.size - bta_ma_stream_used_size(p_stream);
+
+ /* calculate the size to copy (the minimum of string and buffer size */
+ if ( str_size > buf_size )
+ {
+ size = buf_size;
+ p_stream->status = STRM_ERROR_OVERFLOW;
+ }
+ else
+ size = str_size;
+
+ /* copy the data and move the pointer */
+ memcpy(p_stream->u.mem.p_next, p_str, size);
+ p_stream->u.mem.p_next += size;
+ }
+ break;
+
+ case STRM_TYPE_FILE:
+ /* write string */
+ bta_ma_co_write(p_stream->u.file.fd, p_str, str_size);
+ break;
+ }
+
+ /* return TRUE if stream is OK */
+ return(p_stream->status == STRM_SUCCESS);
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_buf
+**
+** Description Stream a buffer into the buffer.
+**
+** Parameters p_stream - pointer to stream information.
+** len - length of buffer
+** p_buf - pointer to buffer to stream.
+**
+** Returns TRUE if the buffer was large enough to hold the data.
+**
+*******************************************************************************/
+extern BOOLEAN bta_ma_stream_buf(tBTA_MA_STREAM * p_stream,
+ UINT16 len,
+ UINT8 * p_buf)
+{
+ UINT16 buf_size;
+ UINT16 size = 0;
+
+ /* ensure stream and buffer pointer are not NULL */
+ if ( !p_buf || !p_stream )
+ return(FALSE);
+
+ switch ( p_stream->type )
+ {
+ case STRM_TYPE_MEMORY:
+ /* ensure buffer is not full */
+ if ( p_stream->status == STRM_SUCCESS )
+ {
+ /* get amount of size left in buffer */
+ buf_size = p_stream->u.mem.size - bta_ma_stream_used_size(p_stream);
+
+ /* calculate the size to copy (the minimum of string and buffer size */
+ if ( len > buf_size )
+ {
+ size = buf_size;
+ p_stream->status = STRM_ERROR_OVERFLOW;
+ }
+ else
+ size = len;
+
+ /* copy the data and move the pointer */
+ memcpy(p_stream->u.mem.p_next, p_buf, len);
+ p_stream->u.mem.p_next += size;
+ }
+ break;
+ case STRM_TYPE_FILE:
+ /* write string */
+ bta_ma_co_write(p_stream->u.file.fd, p_buf, len);
+ break;
+ }
+
+ /* return TRUE if stream is OK */
+ return(p_stream->status == STRM_SUCCESS);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_boolean_yes_no
+**
+** Description Stream a yes/no string into the buffer.
+**
+** Parameters p_stream - pointer to stream information.
+** val - a boolean value to indicate yes or no
+**
+** Returns TRUE if the yes/no string was successfully added into
+** the stream.
+**
+*******************************************************************************/
+BOOLEAN bta_ma_stream_boolean_yes_no(tBTA_MA_STREAM * p_stream, BOOLEAN val)
+{
+ return bta_ma_stream_str(p_stream,
+ val == FALSE ? BTA_MSE_BOOLEAN_NO : BTA_MSE_BOOLEAN_YES);
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_value
+**
+** Description Stream an UINT32 value string into the buffer.
+**
+** Parameters p_stream - pointer to stream information.
+** val - a UINT32 value
+**
+** Returns TRUE if the buffer was large enough to hold the data.
+**
+*******************************************************************************/
+BOOLEAN bta_ma_stream_value(tBTA_MA_STREAM * p_stream, UINT32 val)
+{
+ char temp[50];
+
+ sprintf(temp, "%lu", val);
+ return bta_ma_stream_str(p_stream, temp);
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_handle
+**
+** Description Stream a message handle into the buffer.
+**
+** Parameters p_stream - pointer to stream information.
+** handle - handle to be put in the buffer.
+**
+** Returns TRUE if the buffer was large enough to hold the data.
+**
+*******************************************************************************/
+
+BOOLEAN bta_ma_stream_handle(tBTA_MA_STREAM * p_stream, tBTA_MA_MSG_HANDLE handle)
+{
+ char temp[5];
+ int x;
+ BOOLEAN value_yet = FALSE;
+
+ /* ensure buffer is not full */
+ if ( p_stream->status == STRM_SUCCESS )
+ {
+ for ( x=0; x < BTA_MA_HANDLE_SIZE; x++ )
+ {
+ /* Skip any leading 0's */
+ if ( (! value_yet) && (handle[x] == 0) )
+ continue;
+
+ value_yet = TRUE;
+
+ sprintf(temp, "%02x", handle[x]);
+
+ if ( bta_ma_stream_str(p_stream, temp) == FALSE )
+ return(FALSE);
+ }
+ }
+
+ /* return TRUE if stream is OK */
+ return(p_stream->status == STRM_SUCCESS);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_used_size
+**
+** Description Returns the used byte count.
+**
+** Parameters p_stream - pointer to stream information.
+**
+** Returns Number of bytes used in the buffer.
+**
+*******************************************************************************/
+
+UINT16 bta_ma_stream_used_size(tBTA_MA_STREAM * p_stream)
+{
+ return(p_stream->u.mem.p_next - p_stream->u.mem.p_buffer);
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_ok
+**
+** Description Determines if the stream is ok.
+**
+** Parameters p_stream - pointer to stream information.
+**
+** Returns TRUE if stream status is OK.
+**
+*******************************************************************************/
+
+BOOLEAN bta_ma_stream_ok(tBTA_MA_STREAM * p_stream)
+{
+ return(p_stream && p_stream->status == STRM_SUCCESS);
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_convert_hex_str_to_64bit_handle
+**
+** Description Convert a hex string to a 64 bit message handle in Big Endian
+** format
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ma_convert_hex_str_to_64bit_handle(char *p_hex_str, tBTA_MA_MSG_HANDLE handle)
+{
+ UINT32 ul1, ul2;
+ UINT8 *p;
+ char tmp[BTA_MA_32BIT_HEX_STR_SIZE];
+ UINT8 str_len;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_convert_hex_str_to_64bit_handle");
+#endif
+
+ str_len = strlen(p_hex_str);
+ memset(handle,0,sizeof(tBTA_MA_MSG_HANDLE));
+
+ if (str_len >= 8)
+ {
+ /* most significant 4 bytes */
+ memcpy(tmp,p_hex_str,(str_len-8));
+ tmp[str_len-8]='\0';
+ ul1 = strtoul(tmp,0,16);
+ p=handle;
+ UINT32_TO_BE_STREAM(p, ul1);
+
+ /* least significant 4 bytes */
+ memcpy(tmp,&(p_hex_str[str_len-8]),8);
+ tmp[8]='\0';
+ ul2 = strtoul(tmp,0,16);
+ p=&handle[4];
+ UINT32_TO_BE_STREAM(p, ul2);
+ }
+ else
+ {
+ /* least significant 4 bytes */
+ ul1 = strtoul(p_hex_str,0,16);
+ p=&handle[4];
+ UINT32_TO_BE_STREAM(p, ul1);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_get_char
+**
+** Description Gets one character from the stream.
+**
+** Parameters p_stream - pointer to stream information.
+** p_char - pointer to where to receive the character.
+**
+** Returns TRUE if character was read OK.
+**
+*******************************************************************************/
+BOOLEAN bta_ma_get_char(tBTA_MA_STREAM * p_stream, char * p_char)
+{
+ BOOLEAN bStatus = FALSE;
+
+ if ( p_char )
+ {
+ *p_char = 0;
+
+ if ( p_stream )
+ {
+ switch ( p_stream->type )
+ {
+ case STRM_TYPE_MEMORY:
+ if ( (p_stream->u.mem.p_next-p_stream->u.mem.p_buffer) < p_stream->u.mem.size )
+ {
+ *p_char = *p_stream->u.mem.p_next;
+ p_stream->u.mem.p_next++;
+
+ bStatus = TRUE;
+ }
+ break;
+ case STRM_TYPE_FILE:
+ /* read character */
+ bStatus = bta_ma_co_read(p_stream->u.file.fd, (void *) p_char, 1) == 1;
+ break;
+ }
+ }
+ }
+
+ return( bStatus );
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ma_get_tag
+**
+** Description Parses a tag from the stream. Basically this returns any text
+** before a ':' character, ignoring leading whitespace.
+**
+** Parameters p_stream - Input stream.
+** psz - buffer to receive the tag
+** max_size - size of the receiving buffer (including space
+** for the NULL character.
+**
+** Returns Size of tag, or 0 if there was an error.
+**
+*******************************************************************************/
+UINT16 bta_ma_get_tag(tBTA_MA_STREAM * p_stream, char * psz, UINT16 max_size)
+{
+ char c;
+ UINT16 count = 0;
+
+ /* handle bad arguments */
+ if ( p_stream && psz && (max_size > 0) )
+ {
+ /* reserve last byte for NULL terminator */
+ max_size--;
+
+ while ( bta_ma_get_char(p_stream, &c)
+ && (c != ':')
+ && (count < max_size) )
+ {
+ /* ignore leading whitespace */
+ if ( !count && ((c == ' ') || (c == '\t')) )
+ continue;
+
+ /* if we hit a CR, return 0 to indicate an error */
+ if ( c == '\r' )
+ return( 0 );
+
+ psz[count++] = c;
+ }
+
+ /* Either we hit a problem reading from the stream
+ ** or the buffer was not large enough
+ */
+ if ( c != ':' )
+ return( 0 );
+
+ /* terminate string */
+ psz[count] = '\0';
+ }
+
+ return( count );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_get_value
+**
+** Description Parses a value from the stream. Basically this any text
+** up to (but not including) the CR LF sequence.
+**
+** Parameters p_stream - Input stream.
+** psz - buffer to receive the value
+** max_size - size of the receiving buffer (including space
+** for the NULL character.
+**
+** Returns Size of value, or 0 if there was an error.
+**
+*******************************************************************************/
+UINT16 bta_ma_get_value(tBTA_MA_STREAM * p_stream, char * psz, UINT16 max_size)
+{
+ char c;
+ UINT16 count = 0;
+
+ /* handle bad arguments */
+ if ( p_stream && psz && (max_size > 0) )
+ {
+ /* reserve last byte for NULL terminator */
+ max_size--;
+
+ while ( bta_ma_get_char(p_stream, &c)
+ && (c != '\r')
+ && (count < max_size) )
+ {
+ psz[count++] = c;
+ }
+
+ /* Either we hit a problem reading from the stream
+ ** or the buffer was not large enough
+ */
+ if ( c != '\r' )
+ return( 0 );
+
+ /* burn the next character which must be LF */
+ if ( ! bta_ma_get_char(p_stream, &c) )
+ return( 0 );
+
+ /* terminate string */
+ psz[count] = '\0';
+ }
+
+ return( count );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_get_param
+**
+** Description Parses the parameter from the source string.
+**
+** Parameters p_src - source paramter string.
+** psz - buffer to receive the value
+**
+** Returns Size of param, or 0 if there was an error.
+**
+*******************************************************************************/
+UINT16 bta_ma_get_param(char *p_src, char *psz )
+{
+ char c;
+ UINT16 count = 0;
+ BOOLEAN first_semicolon_found=FALSE;
+
+ /* handle bad arguments */
+ if ( p_src && psz )
+ {
+ while ( (c = *p_src++) )
+ {
+
+ /* throw away the first ';' */
+ if ( !count && (c==';') )
+ {
+ first_semicolon_found = TRUE;
+ continue;
+ }
+
+ /* first char should be ';' otherwise return 0 */
+ if(!count && !first_semicolon_found && (c!=';'))
+ return (0);
+
+ /* if we hit a CR, return 0 to indicate an error */
+ if ( c == '\r' )
+ return( 0 );
+
+ psz[count++] = c;
+ }
+
+ if ( !count )
+ return( 0 );
+
+ /* terminate string */
+ psz[count] = '\0';
+ }
+
+ return( count );
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_ma_parse_vcard
+**
+** Description Parses a vCard from the stream into a generic tBTA_MA_BMSG_VCARD
+** structure.
+**
+** Parameters p_vcard - pointer to generic vCard structure.
+** p_stream - Input stream.
+**
+** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not.
+**
+*******************************************************************************/
+tBTA_MA_STATUS bta_ma_parse_vcard(tBTA_MA_BMSG_VCARD * p_vcard,
+ tBTA_MA_STREAM * p_stream)
+{
+ char sz[BTA_MA_MAX_SIZE];
+ tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL;
+ tBTA_MA_VCARD_VERSION version;
+ char * psztoken_tel = "TEL";
+// btla-specific ++
+ char * psztoken_name = "N;";
+// btla-specific --
+ char param[BTA_MA_MAX_SIZE];
+ char *p_src;
+ UINT16 len;
+
+
+ while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) )
+ {
+ if ( strcmp(sz, "VERSION") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ if ( strcmp(sz, "3.0") == 0 )
+ version = BTA_MA_VCARD_VERSION_30;
+ else if ( strcmp(sz, "2.1") == 0 )
+ version = BTA_MA_VCARD_VERSION_21;
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ma_parse_vcard - Invalid vcard version: '%s'", sz);
+ break;
+ }
+
+ BTA_MaBmsgSetVcardVersion(p_vcard, version);
+ }
+ else if ( strcmp(sz, "N") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_N, sz, NULL);
+// btla-specific ++
+ }
+ else if ( strstr(sz, psztoken_name) == sz )
+ {
+ p_src = sz + strlen(psztoken_name) - 1; // move to (first) semicolon, not past it
+ len = strlen(p_src);
+ if ( (len < BTA_MA_MAX_SIZE) && bta_ma_get_param(p_src, param))
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_N, sz, param);
+ }
+// btla-specific --
+ }
+ else if ( strcmp(sz, "FN") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_FN, sz, NULL);
+ }
+ else if ( strcmp(sz, psztoken_tel ) == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_TEL, sz, NULL);
+ }
+ else if ( strstr(sz, psztoken_tel) == sz )
+ {
+ p_src = sz + strlen(psztoken_tel);
+ len = strlen(p_src);
+ if ( (len < BTA_MA_MAX_SIZE) && bta_ma_get_param(p_src, param))
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_TEL, sz, param);
+ }
+ }
+ else if ( strcmp(sz, "EMAIL") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgAddVcardProp(p_vcard, BTA_MA_VCARD_PROP_EMAIL, sz, NULL);
+ }
+ else if ( strcmp(sz, "END") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ status = BTA_MA_STATUS_OK;
+ break;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ma_parse_vcard - Invalid tag: '%s'", sz);
+ }
+ }
+
+ return( status );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_parse_content
+**
+** Description Parses a <bmessage-body-content> from the stream into a
+** generic tBTA_MA_BMSG_CONTENT structure. This will parse text until
+** we see "END:MSG" at the start of a line.
+**
+** Parameters p_content - pointer to generic content structure.
+** p_stream - Input stream.
+**
+** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not.
+**
+*******************************************************************************/
+tBTA_MA_STATUS bta_ma_parse_content(tBTA_MA_BMSG_CONTENT * p_content,
+ tBTA_MA_STREAM * p_stream)
+{
+/* This constant defines the size of the work buffer used for parsing.
+** It MUST be larger than the 'END:MSG<CRLF>" string size. The larger
+** the buffer the more efficient this parser will be.
+*/
+#define BTA_MA_PARSE_BUF_SIZE BTA_MA_MAX_SIZE
+
+/* These constants define the four states the parser can be in.
+*/
+#define STATE_WS (0) /* checking for leading whitespace */
+#define STATE_END (1) /* checking for END:MSG */
+#define STATE_CR (2) /* checking for CRLF */
+#define STATE_TEXT (3) /* copying text */
+
+ static const char * END_MSG = "END:MSG\r\n";
+
+ char sz[BTA_MA_PARSE_BUF_SIZE+1];
+ char c;
+ int state = STATE_WS; /* start in the 'whitespace' state */
+ int idx_commit = 0;
+ int idx_trial = 0;
+ int idx_end = 0;
+ int x;
+
+ /* NOTES - There are 3 primary indices used during parsing:
+ **
+ ** 'idx_commit' these are characters that are commited to being
+ ** in the message text. We need to be able to save characters
+ ** (such as <CR><LF>, "END..", etc.) but not actually 'commit' them.
+ **
+ ** 'idx_trial' these are characters that we are saving on a trial
+ ** basis until we know what to do with them. For example, if
+ ** we get a sequence "<CR>+<LF>+E+N", we don't want to commit
+ ** them until we know it is not "END:MSG<CR><LF>".
+ **
+ ** 'idx_end' is used to index through the "END:MSG<CR><LF> string.
+ */
+
+ /* Handle bad arguments */
+ if ( p_stream && p_content )
+ {
+ /* Get one character from the stream */
+ while ( bta_ma_get_char(p_stream, &c) )
+ {
+ switch (state)
+ {
+ case STATE_WS:
+ /* totally ignore leading whitespace */
+ if ( (c == ' ') || (c == '\t') )
+ continue;
+
+ /* Otherwise intentionaly fall through after resetting the
+ ** 'end' index so we start comparing from the beginning.
+ */
+ idx_end = 0;
+
+ case STATE_END:
+ /* Is the character in the "END:MSG<CR><LF> sequence? */
+ if ( c == END_MSG[idx_end] )
+ {
+ /* Yes. Did we get to the end of "END:MSG<cr><lf>"? */
+ if ( ! END_MSG[++idx_end] )
+ {
+ /* Yes. Commit any characters and get out. */
+ if ( idx_commit )
+ {
+ sz[idx_commit] = '\0';
+ BTA_MaBmsgAddMsgContent(p_content, sz);
+ }
+
+ return( BTA_MA_STATUS_OK );
+ }
+
+ state = STATE_END;
+ break;
+ }
+ /* If we fell through from the whitespace state
+ ** then we should commit all chars at this point.
+ ** It handles the case where we get consecutive CRLF.
+ */
+ if ( state == STATE_WS )
+ idx_commit = idx_trial;
+
+ /* And intentionally fall through */
+
+ case STATE_CR:
+ /* We got <CR>, is this <LF>? */
+ if ( c == '\n' )
+ {
+ /* Now look for any whitespace */
+ state = STATE_WS;
+ break;
+ }
+
+ /* otherwise intentionally fall through */
+
+ case STATE_TEXT:
+ /* is a CR? */
+ if ( c == '\r' )
+ state = STATE_CR; /* Look for <LF> */
+ else
+ state = STATE_TEXT; /* Copy the text */
+ break;
+ }
+
+ /* All (non-whitespace) characters are copied to
+ ** the buffer as 'trial' characters possibly
+ ** committed later.
+ */
+ sz[idx_trial++] = c;
+
+ /* If we are in the text copy state, then
+ ** commit all characters to this point.
+ */
+ if ( state == STATE_TEXT )
+ idx_commit = idx_trial;
+
+ /* The buffer is full. Commit the good characters
+ ** to the message content, and rearrange the rest
+ ** of the text to make room for more.
+ */
+ if ( idx_trial == BTA_MA_PARSE_BUF_SIZE )
+ {
+ /* Do we have characters to commit?
+ ** If we don't we are in trouble.
+ */
+ if ( idx_commit )
+ {
+ /* Save the last character so we can put a NULL there. */
+ c = sz[idx_commit];
+ sz[idx_commit] = '\0';
+ BTA_MaBmsgAddMsgContent(p_content, sz);
+
+ /* Do we need to rearrange uncommited text? */
+ if ( idx_commit != idx_trial )
+ {
+ /* Restore character */
+ sz[idx_commit] = c;
+
+ /* Copy the 'trial' characters to the beginning of buffer */
+ idx_trial -= idx_commit;
+ for ( x=0; x < idx_trial; x++)
+ sz[x] = sz[x+idx_commit];
+ idx_commit = 0;
+ }
+ else
+ {
+ idx_trial = idx_commit = 0;
+ }
+ }
+ else
+ {
+ /* ERROR - no space to shuffle things around */
+ APPL_TRACE_ERROR0("bta_ma_parse_content - work buffer too small");
+ break;
+ }
+ }
+ }
+ }
+
+ return( BTA_MA_STATUS_FAIL );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_parse_body
+**
+** Description Parses a <bmessage-content> (BBODY) from the stream into a
+** generic tBTA_MA_BMSG_BODY structure. This will parse text until
+** we see "END:BODY" at the start of a line.
+**
+** Parameters p_body - pointer to generic content body structure.
+** p_stream - Input stream.
+**
+** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not.
+**
+*******************************************************************************/
+tBTA_MA_STATUS bta_ma_parse_body(tBTA_MA_BMSG_BODY * p_body,
+ tBTA_MA_STREAM * p_stream)
+{
+ char sz[BTA_MA_MAX_SIZE];
+ tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL;
+ tBTA_MA_BMSG_CONTENT *p_content = NULL;
+ tBTA_MA_BMSG_ENCODING encoding;
+ tBTA_MA_BMSG_LANGUAGE language;
+ tBTA_MA_CHARSET charset;
+
+ while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) )
+ {
+ if ( strcmp(sz, "PARTID") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ BTA_MaBmsgSetBodyPartid(p_body, (UINT16) atoi(sz));
+ }
+ else if ( strcmp(sz, "ENCODING") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ if ( bta_ma_str_to_encoding(sz, &encoding) )
+ BTA_MaBmsgSetBodyEncoding(p_body, encoding);
+ else
+ APPL_TRACE_ERROR1("bta_ma_parse_body - Invalid ENCODING: '%s'", sz);
+ }
+ else if ( strcmp(sz, "CHARSET") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ if ( bta_ma_str_to_charset(sz, &charset))
+ BTA_MaBmsgSetBodyCharset(p_body, charset);
+ else
+ APPL_TRACE_ERROR1("bta_ma_parse_body - invalid CHARSET: '%s'", sz);
+ }
+ else if ( strcmp(sz, "LANGUAGE") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ if ( bta_ma_str_to_language(sz, &language) )
+ BTA_MaBmsgSetBodyLanguage(p_body, language);
+ else
+ APPL_TRACE_ERROR1("bta_ma_parse_body - Invalid LANGUAGE: '%s'", sz);
+ }
+ else if ( strcmp(sz, "LENGTH") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ /* we don't really care about the length */
+ }
+ else if ( strcmp(sz, "BEGIN") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+
+ if ( strcmp(sz, "MSG") == 0 )
+ {
+ p_content = BTA_MaBmsgAddContentToBody(p_body);
+ bta_ma_parse_content(p_content, p_stream);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ma_parse_body - Invalid BEGIN: '%s'", sz);
+ }
+ }
+ else if ( strcmp(sz, "END") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ status = BTA_MA_STATUS_OK;
+ break;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ma_parse_body - Invalid tag: '%s'", sz);
+ }
+ }
+
+ return( status );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_parse_envelope
+**
+** Description Parses a <bmessage-envelope> from the stream into a
+** generic tBTA_MA_BMSG_ENVELOPE structure. This will parse text
+** until we see "END:BENV" at the start of a line.
+**
+** Parameters p_envelope - pointer to generic envelope structure.
+** p_stream - Input stream.
+**
+** Returns BTA_MA_STATUS_OK if successful. BTA_MA_STATUS_FAIL if not.
+**
+*******************************************************************************/
+tBTA_MA_STATUS bta_ma_parse_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope,
+ tBTA_MA_STREAM * p_stream)
+{
+ char sz[BTA_MA_MAX_SIZE];
+ tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL;
+ tBTA_MA_BMSG_VCARD * p_vcard = NULL;
+ tBTA_MA_BMSG_ENVELOPE * p_new_envelope = NULL;
+ tBTA_MA_BMSG_BODY * p_body = NULL;
+
+ while ( bta_ma_get_tag(p_stream, sz, BTA_MA_MAX_SIZE) )
+ {
+ if ( strcmp(sz, "BEGIN") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+
+ if ( strcmp(sz, "VCARD") == 0 )
+ {
+ p_vcard = BTA_MaBmsgAddRecipToEnv(p_envelope);
+ bta_ma_parse_vcard(p_vcard, p_stream);
+ }
+ else if ( strcmp(sz, "BENV") == 0 )
+ {
+ p_new_envelope = BTA_MaBmsgAddEnvToEnv(p_envelope);
+ bta_ma_parse_envelope(p_new_envelope, p_stream);
+ }
+ else if ( strcmp(sz, "BBODY") == 0 )
+ {
+ p_body = BTA_MaBmsgAddBodyToEnv(p_envelope);
+ bta_ma_parse_body(p_body, p_stream);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ma_parse_envelope - Invalid BEGIN: '%s'", sz);
+ }
+
+ }
+ else if ( strcmp(sz, "END") == 0 )
+ {
+ bta_ma_get_value(p_stream, sz, BTA_MA_MAX_SIZE);
+ status = BTA_MA_STATUS_OK;
+ break;
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("bta_ma_parse_envelope - Invalid tag: '%s'", sz);
+ }
+ }
+
+ return( status );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_vcards
+**
+** Description Builds vCards into a stream.
+**
+** Parameters p_stream - Output stream.
+** p_vcard - pointer to single vCard that may be linked to
+** additional vCards.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ma_stream_vcards(tBTA_MA_STREAM * p_stream,
+ tBTA_MA_BMSG_VCARD * p_vcard)
+{
+ int x;
+
+ /* vCards are formatted one after another */
+ while ( p_stream && p_vcard )
+ {
+ bta_ma_stream_str(p_stream, "\r\nBEGIN:VCARD");
+
+ /* version */
+ bta_ma_stream_str(p_stream, "\r\nVERSION:");
+ bta_ma_stream_str(p_stream,
+ p_vcard->version == BTA_MA_VCARD_VERSION_21 ? "2.1" : "3.0");
+
+ /* vcard properties */
+ for (x=0; x < BTA_MA_VCARD_PROP_MAX; x++)
+ bta_ma_stream_vcard_prop(p_stream, p_vcard,(tBTA_MA_VCARD_PROP) x);
+
+ bta_ma_stream_str(p_stream, "\r\nEND:VCARD");
+
+ /* Get the next vCard and repeat */
+ p_vcard = BTA_MaBmsgGetNextVcard(p_vcard);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_vcard_prop
+**
+** Description Builds a property and values into a stream. This will
+** build all of the property/values for one property (i.e.
+** can be multiple EMAIL propeties set). It will only
+** format the property if it has a value (except the N/name
+** if a 2.1 vCard and FN/fullname property of a 3.0 vCard
+** will always be output).
+**
+** Parameters p_stream - Output stream.
+** p_vcard - pointer to vCard.
+** prop - property.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ma_stream_vcard_prop(tBTA_MA_STREAM * p_stream,
+ tBTA_MA_BMSG_VCARD * p_vcard,
+ tBTA_MA_VCARD_PROP prop)
+{
+ tBTA_MA_VCARD_PROPERTY * p_prop;
+ tBTA_MA_VCARD_VERSION version;
+ char * p_param;
+ char * p_value;
+
+ if ( p_vcard && prop < BTA_MA_VCARD_PROP_MAX )
+ {
+ p_prop = BTA_MaBmsgGetVcardProp(p_vcard, prop);
+
+ do
+ {
+ p_param = BTA_MaBmsgGetVcardPropParam(p_prop);
+ p_value = BTA_MaBmsgGetVcardPropValue(p_prop);
+ version = BTA_MaBmsgGetVcardVersion(p_vcard);
+
+ if ( (p_value && strlen(p_value))
+ || ((version == BTA_MA_VCARD_VERSION_21) && (prop == BTA_MA_VCARD_PROP_N))
+ || ((version == BTA_MA_VCARD_VERSION_30) && (prop <= BTA_MA_VCARD_PROP_FN)) )
+ {
+ /* property name */
+ bta_ma_stream_str(p_stream, "\r\n");
+ bta_ma_stream_str(p_stream, vcard_prop_name[prop]);
+
+
+ /* property parameter */
+ if ( p_param )
+ {
+ bta_ma_stream_str(p_stream, ";");
+ bta_ma_stream_str(p_stream, p_param);
+ }
+
+ /* property value */
+ bta_ma_stream_str(p_stream, ":");
+ bta_ma_stream_str(p_stream, p_value);
+ }
+
+ /* There may be multiple instances of a property (e.g. 2 TEL numbers */
+ p_prop = BTA_MaBmsgGetNextVcardProp(p_prop);
+
+ } while ( p_prop );
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_envelopes
+**
+** Description Builds a envelope <bmessage-envelope> (or series of
+** envelopes) into a stream.
+**
+** Parameters p_stream - Output stream.
+** p_envelope - pointer to envelope structure.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ma_stream_envelopes(tBTA_MA_STREAM * p_stream,
+ tBTA_MA_BMSG_ENVELOPE * p_envelope)
+{
+ tBTA_MA_BMSG_BODY * p_body;
+
+ if ( p_stream && p_envelope )
+ {
+ bta_ma_stream_str(p_stream, "\r\nBEGIN:BENV");
+
+ /* Recipients */
+ bta_ma_stream_vcards(p_stream, BTA_MaBmsgGetRecipFromEnv(p_envelope));
+
+ /* It will either be another (nested) envelope or the body */
+ p_body = BTA_MaBmsgGetBodyFromEnv(p_envelope);
+
+ if ( p_body )
+ bta_ma_stream_body(p_stream, p_body);
+ else
+ bta_ma_stream_envelopes(p_stream, BTA_MaBmsgGetNextEnv(p_envelope));
+
+ bta_ma_stream_str(p_stream, "\r\nEND:BENV");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_body
+**
+** Description Builds a bMessage content <bmessage-content> into a stream.
+**
+** Parameters p_stream - Output stream.
+** p_body - pointer to bBody structure.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ma_stream_body(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_BODY * p_body)
+{
+ UINT16 part_id = 0;
+ tBTA_MA_BMSG_LANGUAGE language;
+ tBTA_MA_CHARSET charset;
+
+ if ( p_stream && p_body )
+ {
+ bta_ma_stream_str(p_stream, "\r\nBEGIN:BBODY");
+
+ /* Part ID (optional) */
+ part_id = BTA_MaBmsgGetBodyPartid(p_body);
+ if ( part_id != 0 )
+ {
+ bta_ma_stream_str(p_stream, "\r\nPARTID:");
+ bta_ma_stream_value(p_stream, part_id);
+ }
+
+ /* Character set */
+ charset = BTA_MaBmsgGetBodyCharset(p_body);
+ switch ( charset)
+ {
+ case BTA_MA_CHARSET_UTF_8:
+ bta_ma_stream_str(p_stream, "\r\nCHARSET:UTF-8");
+ break;
+ case BTA_MA_CHARSET_NATIVE:
+ bta_ma_stream_str(p_stream, "\r\nCHARSET:NATIVE");
+ /* Encoding */
+ bta_ma_stream_str(p_stream, "\r\nENCODING:");
+ bta_ma_stream_str(p_stream, bmsg_body_encoding[BTA_MaBmsgGetBodyEncoding(p_body)]);
+ break;
+ default:
+ break;
+ }
+
+ /* Language */
+ language = BTA_MaBmsgGetBodyLanguage(p_body);
+ if ( language != BTA_MA_BMSG_LANG_UNSPECIFIED )
+ {
+ bta_ma_stream_str(p_stream, "\r\nLANGUAGE:");
+ bta_ma_stream_str(p_stream, bmsg_body_language[language]);
+ }
+
+ /* Body content length */
+ bta_ma_stream_str(p_stream, "\r\nLENGTH:");
+ bta_ma_stream_value(p_stream, bta_ma_get_body_length(p_body));
+
+ /* Content */
+ bta_ma_stream_body_content(p_stream, BTA_MaBmsgGetContentFromBody(p_body));
+
+ bta_ma_stream_str(p_stream, "\r\nEND:BBODY");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_stream_body_content
+**
+** Description Builds a body content <bmessage-body-content> into a stream.
+**
+** Parameters p_stream - Output stream.
+** p_content - pointer to content structure.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ma_stream_body_content(tBTA_MA_STREAM * p_stream,
+ tBTA_MA_BMSG_CONTENT * p_content)
+{
+ char * p_text;
+
+ APPL_TRACE_EVENT0("bta_ma_stream_body_content");
+ while ( p_stream && p_content )
+ {
+ bta_ma_stream_str(p_stream, "\r\nBEGIN:MSG");
+
+ p_text = BTA_MaBmsgGetMsgContent(p_content);
+ if ( p_text )
+ {
+ bta_ma_stream_str(p_stream, "\r\n");
+
+ while ( p_text )
+ {
+ bta_ma_stream_str(p_stream, p_text);
+ p_text = BTA_MaBmsgGetNextMsgContent(p_content);
+ }
+ }
+
+ bta_ma_stream_str(p_stream, "\r\nEND:MSG");
+
+ p_content = BTA_MaBmsgGetNextContent(p_content);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_str_to_charset
+**
+** Description Returns the charset enumeration (tBTA_MA_CHARSET) that
+** corresponds to the provided string.
+**
+** Parameters psz - Input string.
+** p_charset - pointer to the charset value to be received.
+**
+** Returns TRUE if there is a match, otherwise FALSE.
+**
+*******************************************************************************/
+BOOLEAN bta_ma_str_to_charset(char * psz, tBTA_MA_CHARSET * p_charset)
+{
+
+ tBTA_MA_CHARSET e;
+
+ if ( psz && p_charset )
+ {
+ for (e= BTA_MA_CHARSET_NATIVE; e < num_bmsg_body_charset; e++)
+ {
+ if ( strcmp(psz, bmsg_body_charset[e]) == 0 )
+ {
+ *p_charset = e;
+ return( TRUE );
+ }
+ }
+ }
+
+ return( FALSE );
+}
+
+
+/*******************************************************************************
+**
+** Function bta_ma_str_to_encoding
+**
+** Description Returns the encoding enumeration (tBTA_MA_BMSG_ENCODING) that
+** corresponds to the provided string.
+**
+** Parameters psz - Input string.
+** p_encoding - pointer to the encoding value to be received.
+**
+** Returns TRUE if there is a match, otherwise FALSE.
+**
+*******************************************************************************/
+BOOLEAN bta_ma_str_to_encoding(char * psz, tBTA_MA_BMSG_ENCODING * p_encoding)
+{
+ tBTA_MA_BMSG_ENCODING e;
+
+ if ( psz && p_encoding )
+ {
+ for (e= BTA_MA_BMSG_ENC_8BIT; e < num_bmsg_body_encoding; e++)
+ {
+ if ( strcmp(psz, bmsg_body_encoding[e]) == 0 )
+ {
+ *p_encoding = e;
+ return( TRUE );
+ }
+ }
+ }
+
+ return( FALSE );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_str_to_language
+**
+** Description Returns the language enumeration (tBTA_MA_BMSG_LANGUAGE) that
+** corresponds to the provided string.
+**
+** Parameters psz - Input string.
+** p_language - pointer to the language value to be received.
+**
+** Returns TRUE if there is a match, otherwise FALSE.
+**
+*******************************************************************************/
+BOOLEAN bta_ma_str_to_language(char * psz, tBTA_MA_BMSG_LANGUAGE * p_language)
+{
+ tBTA_MA_BMSG_LANGUAGE l;
+
+ if ( psz && p_language )
+ {
+ for (l=BTA_MA_BMSG_LANG_UNSPECIFIED; l < num_bmsg_body_language; l++)
+ {
+ if ( strcmp(psz, bmsg_body_language[l]) == 0 )
+ {
+ *p_language = l;
+ return( TRUE );
+ }
+ }
+ }
+
+ return( FALSE );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_str_to_msg_typ
+**
+** Description Returns the message type enumeration (tBTA_MA_MSG_TYPE)
+** that corresponds to the provided string.
+**
+** Parameters psz - Input string.
+** p_msg_type - pointer to the message type value to be
+** received.
+**
+** Returns TRUE if there is a match, otherwise FALSE.
+**
+*******************************************************************************/
+BOOLEAN bta_ma_str_to_msg_typ(char * psz, tBTA_MA_MSG_TYPE * p_msg_type)
+{
+ if ( psz && p_msg_type )
+ {
+ if ( strcmp(psz, "EMAIL") == 0 )
+ *p_msg_type = BTA_MA_MSG_TYPE_EMAIL;
+ else if ( strcmp(psz, "SMS_GSM") == 0 )
+ *p_msg_type = BTA_MA_MSG_TYPE_SMS_GSM;
+ else if ( strcmp(psz, "SMS_CDMA") == 0 )
+ *p_msg_type = BTA_MA_MSG_TYPE_SMS_CDMA;
+ else if ( strcmp(psz, "MMS") == 0 )
+ *p_msg_type = BTA_MA_MSG_TYPE_MMS;
+ else
+ return FALSE;
+ }
+
+ return( TRUE );
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_get_body_length
+**
+** Description Returns the combined length in characters of the message
+** content.
+**
+** Parameters p_body - pointer to bBody structure.
+**
+** Returns Length of the body message text.
+**
+*******************************************************************************/
+UINT32 bta_ma_get_body_length(tBTA_MA_BMSG_BODY * p_body)
+{
+ UINT32 length = 0, len=0;
+ tBTA_MA_BMSG_CONTENT * p_content;
+ char * p_text;
+
+ APPL_TRACE_EVENT0("bta_ma_get_body_length");
+
+ p_content = BTA_MaBmsgGetContentFromBody(p_body);
+
+ while ( p_content )
+ {
+ p_text= BTA_MaBmsgGetMsgContent(p_content);
+
+ while ( p_text )
+ {
+ len = strlen(p_text);
+ length += (len + BTA_MA_BMSG_BODY_TAG_CTL_LENGTH);
+
+ APPL_TRACE_EVENT3("total=%d len=%d text=%s",length, len, p_text);
+
+ p_text = BTA_MaBmsgGetNextMsgContent(p_content);
+ }
+
+ p_content = BTA_MaBmsgGetNextContent(p_content);
+ }
+
+ APPL_TRACE_EVENT1("bta_ma_get_body_length len=%d", length);
+ return( length );
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_bmsg_free_vcards
+**
+** Description Free buffers used by vVards
+**
+** Parameters p_vcard - Pointer to the first vCard in the linked vCards
+**
+** Returns None
+**
+*******************************************************************************/
+
+void bta_ma_bmsg_free_vcards(tBTA_MA_BMSG_VCARD * p_vcard)
+{
+ int x;
+
+ if ( p_vcard )
+ {
+ /* recursively free any linked vCards */
+ bta_ma_bmsg_free_vcards((tBTA_MA_BMSG_VCARD *)p_vcard->p_next);
+
+ /* Free properties */
+ for (x=0; x < BTA_MA_VCARD_PROP_MAX; x++)
+ bta_ma_bmsg_free_vcard_prop(p_vcard->p_prop[x]);
+
+ /* free vcard structure itself */
+ bta_ma_bmsg_free(p_vcard);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_ma_bmsg_free_envelope
+**
+** Description Free buffers used by envelopes
+**
+** Parameters p_envelope - Pointer to the first envelope in the linked envelopes
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_ma_bmsg_free_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope)
+{
+ if ( p_envelope )
+ {
+ /* recursively free any linked envelopes */
+ bta_ma_bmsg_free_envelope((tBTA_MA_BMSG_ENVELOPE *)p_envelope->p_next);
+
+ /* free the body */
+ bta_ma_bmsg_free_body(p_envelope->p_body);
+
+ /* free recipients */
+ bta_ma_bmsg_free_vcards(p_envelope->p_recip);
+
+ /* free envelope structure itself */
+ bta_ma_bmsg_free(p_envelope);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_ma_bmsg_free_body
+**
+** Description Free buffers used by a message body
+**
+** Parameters p_body - Pointer to a message body
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_ma_bmsg_free_body(tBTA_MA_BMSG_BODY * p_body)
+{
+ if ( p_body )
+ {
+ bta_ma_bmsg_free_content(p_body->p_content);
+
+ /* free body structure itself */
+ bta_ma_bmsg_free(p_body);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_ma_bmsg_free_content
+**
+** Description Free buffers used by message contents
+**
+** Parameters p_envelope - Pointer to the first message content in the
+** linked message contents
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_ma_bmsg_free_content(tBTA_MA_BMSG_CONTENT * p_content)
+{
+ if ( p_content )
+ {
+ /* recursively free any linked content */
+ bta_ma_bmsg_free_content((tBTA_MA_BMSG_CONTENT *)p_content->p_next);
+
+ /* free all of the message text */
+ bta_ma_bmsg_free_message_text(p_content->p_message);
+
+ /* free content structure itself */
+ bta_ma_bmsg_free(p_content);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_ma_bmsg_free_message_text
+**
+** Description Free text string buffers used by a message
+**
+** Parameters p_envelope - Pointer to a message
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_ma_bmsg_free_message_text(tBTA_MA_BMSG_MESSAGE * p_message)
+{
+ tBTA_MA_BMSG_MESSAGE * p_temp;
+
+ while ( p_message )
+ {
+ p_temp = (tBTA_MA_BMSG_MESSAGE *)p_message->p_next;
+
+ /* free message string */
+ bta_ma_bmsg_free(p_message->p_text);
+
+ /* free message text structure */
+ bta_ma_bmsg_free(p_message);
+
+ /* now point to the next one */
+ p_message = p_temp;
+ }
+}
+/*******************************************************************************
+**
+** Function bta_ma_bmsg_free_vcard_prop
+**
+** Description Free buffers used by a vCard property
+**
+** Parameters p_envelope - Pointer to a vCard property
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_ma_bmsg_free_vcard_prop(tBTA_MA_VCARD_PROPERTY * p_prop)
+{
+ if ( p_prop )
+ {
+ /* free the value and the parameter */
+ if ( p_prop->p_value )
+ bta_ma_bmsg_free(p_prop->p_value);
+
+ if ( p_prop->p_param )
+ bta_ma_bmsg_free(p_prop->p_param);
+
+ /* recursively free any linked content */
+ if ( p_prop->p_next )
+ bta_ma_bmsg_free_vcard_prop((tBTA_MA_VCARD_PROPERTY *)p_prop->p_next);
+
+ /* free property structure itself */
+ bta_ma_bmsg_free(p_prop);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ma_bmsg_alloc
+**
+** Description Allocate buffer for the specified size
+**
+** Parameters cb - request buffer size
+**
+** Returns None
+**
+*******************************************************************************/
+
+void * bta_ma_bmsg_alloc(size_t cb)
+{
+ void * p_buf;
+
+ if ((p_buf = GKI_getbuf((UINT16) cb)) == NULL )
+ {
+ APPL_TRACE_ERROR1("Unable to allocate buffer for size=%", (UINT16) cb);
+ }
+ return(p_buf);
+}
+/*******************************************************************************
+**
+** Function bta_ma_bmsg_free
+**
+** Description Free buffer
+**
+** Parameters p - pointer to a buffer
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_ma_bmsg_free(void * p)
+{
+ if ( p )
+ GKI_freebuf(p);
+}
+
+
+#endif /* BTA_MSE_INCLUDED */
diff --git a/bta/ma/bta_ma_util.h b/bta/ma/bta_ma_util.h
new file mode 100644
index 0000000..9040201
--- /dev/null
+++ b/bta/ma/bta_ma_util.h
@@ -0,0 +1,93 @@
+/*****************************************************************************
+**
+** Name: bta_ma_util.h
+**
+** Description: This is the interface file for the Message Access Profile
+** (MAP) utility functions.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_MA_UTIL_H
+#define BTA_MA_UTIL_H
+
+#include "bta_ma_def.h"
+#include "bta_mse_api.h"
+#include "bta_mse_co.h"
+#include "bta_ma_api.h"
+
+
+#define BTA_MA_MAX_SIZE (100)
+
+/* Here are a set of property flags used to keep track
+** of properties that are successfully parsed. We use
+** this information to determine if all the *required*
+** properties have been provided in the parsed object.
+*/
+#define BTA_MA_PROP_VERSION 0x00000001
+#define BTA_MA_BMSG_BODY_TAG_CTL_LENGTH 22 /* see MAP Spec. Errata 3603 */
+ /* BEGIN:MSG<CRTL>+<CRTL>+END:MSG<CRTL> */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ extern const char * bta_ma_evt_typ_to_string(tBTA_MSE_NOTIF_TYPE notif_type);
+ extern const char * bta_ma_msg_typ_to_string(tBTA_MA_MSG_TYPE msg_typ);
+ extern const char * bta_ma_rcv_status_to_string(tBTA_MSE_CO_RCV_STATUS rcv_status);
+
+ extern BOOLEAN bta_ma_stream_str(tBTA_MA_STREAM * p_stream,
+ const char * p_str);
+
+ extern BOOLEAN bta_ma_stream_buf(tBTA_MA_STREAM * p_stream,
+ UINT16 len,
+ UINT8 * p_buf);
+
+ extern BOOLEAN bta_ma_stream_boolean_yes_no(tBTA_MA_STREAM * p_stream, BOOLEAN val);
+
+ extern BOOLEAN bta_ma_stream_value(tBTA_MA_STREAM * p_stream, UINT32 val);
+
+ extern BOOLEAN bta_ma_stream_handle(tBTA_MA_STREAM * p_stream,
+ tBTA_MA_MSG_HANDLE handle);
+
+ extern UINT16 bta_ma_stream_used_size(tBTA_MA_STREAM * p_stream);
+
+ extern BOOLEAN bta_ma_stream_ok(tBTA_MA_STREAM * p_stream);
+
+ extern void bta_ma_convert_hex_str_to_64bit_handle(char *p_hex_str, tBTA_MA_MSG_HANDLE handle);
+
+ extern BOOLEAN bta_ma_get_char(tBTA_MA_STREAM * p_stream, char * p_char);
+ extern BOOLEAN bta_ma_str_to_charset(char * psz, tBTA_MA_CHARSET * p_charset);
+ extern BOOLEAN bta_ma_str_to_encoding(char * psz, tBTA_MA_BMSG_ENCODING * p_encoding);
+ extern BOOLEAN bta_ma_str_to_language(char * psz, tBTA_MA_BMSG_LANGUAGE * p_language);
+ extern BOOLEAN bta_ma_str_to_msg_typ(char * psz, tBTA_MA_MSG_TYPE * p_msg_type);
+
+ extern void bta_ma_stream_vcards(tBTA_MA_STREAM *, tBTA_MA_BMSG_VCARD *);
+ extern void bta_ma_stream_envelopes(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_ENVELOPE * p_envelope);
+ extern void bta_ma_stream_body(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_BODY * p_body);
+ extern void bta_ma_stream_body_content(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_CONTENT * p_content);
+ extern void bta_ma_stream_vcard_prop(tBTA_MA_STREAM * p_stream, tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_VCARD_PROP prop);
+
+ extern UINT32 bta_ma_get_body_length(tBTA_MA_BMSG_BODY * p_body);
+
+ extern UINT16 bta_ma_get_tag(tBTA_MA_STREAM * p_stream, char * psz, UINT16 max_size);
+ extern UINT16 bta_ma_get_value(tBTA_MA_STREAM * p_stream, char * psz, UINT16 max_size);
+
+ extern tBTA_MA_STATUS bta_ma_parse_vcard(tBTA_MA_BMSG_VCARD * p_vcard, tBTA_MA_STREAM * p_stream);
+ extern tBTA_MA_STATUS bta_ma_parse_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope, tBTA_MA_STREAM * p_stream);
+
+ extern void * bta_ma_bmsg_alloc(size_t cb);
+ extern void bta_ma_bmsg_free(void * p);
+ extern void bta_ma_bmsg_free_vcards(tBTA_MA_BMSG_VCARD * p_vcard);
+ extern void bta_ma_bmsg_free_envelope(tBTA_MA_BMSG_ENVELOPE * p_envelope);
+ extern void bta_ma_bmsg_free_body(tBTA_MA_BMSG_BODY * p_body);
+ extern void bta_ma_bmsg_free_content(tBTA_MA_BMSG_CONTENT * p_content);
+ extern void bta_ma_bmsg_free_message_text(tBTA_MA_BMSG_MESSAGE * p_message);
+ extern void bta_ma_bmsg_free_vcard_prop(tBTA_MA_VCARD_PROPERTY * p_prop);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_MA_UTIL_H */
diff --git a/bta/ma/bta_mse_act.c b/bta/ma/bta_mse_act.c
new file mode 100644
index 0000000..c8ec487
--- /dev/null
+++ b/bta/ma/bta_mse_act.c
@@ -0,0 +1,2763 @@
+/*****************************************************************************
+**
+** Name: bta_mse_act.c
+**
+** Description: This file contains the message access server action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "sdp_api.h"
+#include "bta_sys.h"
+#include "port_api.h"
+#include "obx_api.h"
+#include "sdp_api.h"
+#include "bta_fs_api.h"
+#include "bta_mse_api.h"
+#include "bta_mse_int.h"
+#include "bta_fs_co.h"
+#include "utl.h"
+#include "bd.h"
+#include "bta_ma_def.h"
+
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+void bta_mse_req_app_access(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+static void bta_mse_mn_sdp_cback0(UINT16 status);
+static void bta_mse_mn_sdp_cback1(UINT16 status);
+static void bta_mse_mn_sdp_cback2(UINT16 status);
+static void bta_mse_mn_sdp_cback3(UINT16 status);
+static void bta_mse_mn_sdp_cback4(UINT16 status);
+static void bta_mse_mn_sdp_cback5(UINT16 status);
+static void bta_mse_mn_sdp_cback6(UINT16 status);
+
+static tSDP_DISC_CMPL_CB * const bta_mse_mn_sdp_cback_arr[] = {
+ bta_mse_mn_sdp_cback0,
+ bta_mse_mn_sdp_cback1,
+ bta_mse_mn_sdp_cback2,
+ bta_mse_mn_sdp_cback3,
+ bta_mse_mn_sdp_cback4,
+ bta_mse_mn_sdp_cback5,
+ bta_mse_mn_sdp_cback6
+};
+
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+static char *bta_mse_obx_evt_code(UINT16 evt_code);
+#endif
+
+
+/*******************************************************************************
+** Message Access Server (MAS) Action functions
+**
+*******************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_int_close
+**
+** Description Porcesses the Internal MAS session close event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_int_close(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ BD_ADDR bd_addr;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_int_close inst idx=%d sess idx=%d",inst_idx, sess_idx);
+#endif
+
+ if (OBX_GetPeerAddr(p_cb->obx_handle, bd_addr) != 0)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("Send Obx Discon rsp obx session id=%d",
+ p_cb->obx_handle);
+#endif
+ /* resources will be freed at BTA_MSE_MA_OBX_CLOSE_EVT */
+ OBX_DisconnectRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, NULL);
+ }
+ else
+ {
+ /* OBX close already */
+ bta_mse_ma_sm_execute(inst_idx, sess_idx, BTA_MSE_MA_OBX_CLOSE_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_upd_ibx_rsp
+**
+** Description Processes the API update inbox response event.
+** If permission had been granted, continue the operation,
+** otherwise stop the operation.
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_api_upd_ibx_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 rsp_code = OBX_RSP_UNAUTHORIZED;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_api_upd_ibx_rsp inst idx=%d sess idx=%d",inst_idx, sess_idx);
+#endif
+
+ /* Process the currently active access response */
+ if (p_cb->oper == BTA_MSE_OPER_UPDATE_INBOX)
+ {
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE);
+ if (p_data->api_upd_ibx_rsp.rsp == BTA_MSE_UPDATE_INBOX_ALLOW)
+ {
+ bta_mse_co_update_inbox(p_cb->obx_handle, bta_mse_cb.app_id);
+ rsp_code = OBX_RSP_OK;
+ }
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+ else
+ {
+ APPL_TRACE_WARNING1("MSE UPDIBXRSP: Unknown tBTA_MSE_OPER value (%d)",
+ p_cb->oper);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_set_notif_reg_rsp
+**
+** Description Processes the API set notification registration response event.
+** If permission had been granted, continue the operation,
+** otherwise stop the operation.
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_api_set_notif_reg_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_api_set_notif_reg_rsp inst idx=%d sess idx=%d",inst_idx, sess_idx);
+#endif
+
+ /* Process the currently active access response */
+ if ( p_cb->oper == BTA_MSE_OPER_NOTIF_REG)
+ {
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE);
+ if (p_data->api_set_notif_reg_rsp.rsp == BTA_MSE_SET_NOTIF_REG_ALLOW)
+ {
+ bta_mse_proc_notif_reg_status(p_cb->notif_reg_req.notif_status,
+ inst_idx, sess_idx);
+ }
+ else
+ {
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+ }
+ else
+ {
+ APPL_TRACE_WARNING1("MSE SETNOTIFREGRSP: Unknown tBTA_MSE_OPER value (%d)",
+ p_cb->oper);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_accessrsp
+**
+** Description Processes the API access response event.
+** If permission had been granted, continue the operation,
+** otherwise stop the operation.
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+
+void bta_mse_ma_api_accessrsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 rsp_code = OBX_RSP_OK;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("bta_mse_ma_api_accessrsp inst idx=%d sess idx=%d access_rsp=%d",
+ inst_idx, sess_idx,
+ p_data->api_access_rsp.rsp);
+#endif
+
+ if (p_cb->oper != p_data->api_access_rsp.oper )
+ {
+ APPL_TRACE_WARNING2("MSE MA ACCRSP: not match active:%d, rsp:%d",
+ p_cb->oper, p_data->api_access_rsp.oper);
+ return;
+ }
+
+ /* Process the currently active access response */
+ switch (p_cb->oper)
+ {
+ case BTA_MSE_OPER_SETPATH:
+
+ if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW)
+ {
+ bta_mse_co_set_folder( p_cb->obx_handle, p_cb->sp.p_path, bta_mse_cb.app_id);
+ /* updat the working dir */
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->sp.p_path, p_bta_fs_cfg->max_path_len);
+ }
+ else
+ {
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ }
+
+ utl_freebuf((void**)&(p_cb->sp.p_path));
+ utl_freebuf((void**)&(p_cb->sp.p_name));
+ OBX_SetPathRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE);
+ break;
+
+ case BTA_MSE_OPER_GET_MSG_LIST:
+
+ if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW)
+ {
+ bta_mse_getmsglist(inst_idx,sess_idx, TRUE);
+ }
+ else
+ {
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL);
+ bta_mse_clean_msg_list(inst_idx,sess_idx);
+ }
+ break;
+
+ case BTA_MSE_OPER_GET_MSG:
+
+ if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW)
+ {
+ bta_mse_getmsg(inst_idx,sess_idx, TRUE);
+ }
+ else
+ {
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL);
+ bta_mse_clean_msg(inst_idx,sess_idx);
+ }
+ break;
+
+ case BTA_MSE_OPER_PUSH_MSG:
+
+ if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW)
+ {
+ bta_mse_pushmsg(inst_idx, sess_idx, TRUE);
+ }
+ else
+ {
+ OBX_PutRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL);
+ bta_mse_clean_push_msg(inst_idx,sess_idx);
+ }
+ break;
+
+ case BTA_MSE_OPER_DEL_MSG:
+
+ if (p_data->api_access_rsp.rsp == BTA_MA_ACCESS_TYPE_ALLOW)
+ {
+ p_cb->cout_active = TRUE;
+ bta_mse_co_set_msg_delete_status((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ p_cb->set_msg_sts.handle,
+ p_cb->set_msg_sts.sts_val,
+ BTA_MSE_CI_DEL_MSG_EVT,
+ bta_mse_cb.app_id);
+ }
+ else
+ {
+ OBX_PutRsp(p_cb->obx_handle, OBX_RSP_UNAUTHORIZED, (BT_HDR *)NULL);
+ bta_mse_clean_set_msg_sts(inst_idx,sess_idx);
+ }
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("MSE ACCRSP: Unknown tBTA_MSE_OPER value (%d)",
+ p_cb->oper);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_ci_get_folder_entry
+**
+** Description Proceses the get folder entry call-in event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_ci_get_folder_entry(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 rsp_code = OBX_RSP_PART_CONTENT;
+ BOOLEAN free_pkt = TRUE;
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_ci_get_folder_entry inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+#endif
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED);
+ return;
+ }
+
+ /* Process dirent listing call-in event if operation is still active */
+ if (p_cb->oper == BTA_MSE_OPER_GET_FOLDER_LIST)
+ {
+ switch (p_data->ci_get_fentry.status)
+ {
+ case BTA_MA_STATUS_OK: /* Valid new entry */
+ free_pkt = FALSE;
+ rsp_code = bta_mse_add_list_entry(inst_idx, sess_idx);
+ break;
+
+ case BTA_MA_STATUS_EODIR: /* End of list (entry not valid) */
+ free_pkt = FALSE;
+ rsp_code = OBX_RSP_OK;
+ break;
+
+ case BTA_MA_STATUS_FAIL: /* Error occurred */
+ rsp_code = OBX_RSP_NOT_FOUND;
+ break;
+
+ default:
+ APPL_TRACE_ERROR1("bta_mse_ma_ci_get_folder_entry Unknown status=%d ",
+ p_data->ci_get_fentry.status );
+ rsp_code = OBX_RSP_NOT_FOUND;
+ break;
+ }
+ }
+
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_mse_end_of_list(inst_idx, sess_idx,rsp_code);
+
+ if (free_pkt)
+ utl_freebuf((void **)&p_cb->obx.p_pkt);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_ci_get_ml_info
+**
+** Description Proceses the get message list info call-in event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_ci_get_ml_info(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 rsp_code = OBX_RSP_PART_CONTENT;
+ BOOLEAN free_pkt = TRUE;
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_ci_get_ml_info inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+#endif
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED);
+ return;
+ }
+
+ /* Process dirent listing call-in event if operation is still active */
+ if (p_cb->oper == BTA_MSE_OPER_GET_MSG_LIST)
+ {
+ switch (p_data->ci_get_ml_info.status)
+ {
+ case BTA_MA_STATUS_OK: /* Valid new entry */
+ free_pkt = FALSE;
+ rsp_code = bta_mse_add_msg_list_info(inst_idx, sess_idx);
+ break;
+
+ case BTA_MA_STATUS_EODIR: /* End of list (entry not valid) */
+ free_pkt = FALSE;
+ rsp_code = OBX_RSP_OK;
+ break;
+
+ case BTA_MA_STATUS_FAIL: /* Error occurred */
+ rsp_code = OBX_RSP_NOT_FOUND;
+ break;
+
+ default:
+ APPL_TRACE_ERROR1("bta_mse_ma_ci_get_ml_info Unknown status=%d ",
+ p_data->ci_get_ml_info.status );
+ rsp_code = OBX_RSP_NOT_FOUND;
+ break;
+ }
+ }
+
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_mse_end_of_msg_list(inst_idx, sess_idx,rsp_code);
+
+ if (free_pkt)
+ utl_freebuf((void **)&p_cb->obx.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_ci_get_msg_entry
+**
+** Description Proceses the get message entry call-in event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_ci_get_ml_entry(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 rsp_code = OBX_RSP_PART_CONTENT;
+ BOOLEAN free_pkt = TRUE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_ci_get_msg_entry inst idx=%d sess idx=%d",inst_idx, sess_idx);
+ APPL_TRACE_EVENT1(" status=%d",p_data->ci_get_ml_entry.status);
+#endif
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED);
+ return;
+ }
+
+ /* Process dirent listing call-in event if operation is still active */
+ if (p_cb->oper == BTA_MSE_OPER_GET_MSG_LIST)
+ {
+ switch (p_data->ci_get_ml_entry.status)
+ {
+ case BTA_MA_STATUS_OK: /* Valid new entry */
+ free_pkt = FALSE;
+ rsp_code = bta_mse_add_msg_list_entry(inst_idx, sess_idx);
+ break;
+
+ case BTA_MA_STATUS_EODIR: /* End of list (entry not valid) */
+ free_pkt = FALSE;
+ rsp_code = OBX_RSP_OK;
+ break;
+
+ case BTA_MA_STATUS_FAIL: /* Error occurred */
+ rsp_code = OBX_RSP_NOT_FOUND;
+ break;
+
+ default:
+ APPL_TRACE_ERROR1("bta_mse_ma_ci_get_ml_entry Unknown status=%d ",
+ p_data->ci_get_ml_entry.status);
+ rsp_code = OBX_RSP_NOT_FOUND;
+ break;
+ }
+ }
+
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_mse_end_of_msg_list(inst_idx, sess_idx,rsp_code);
+
+ if (free_pkt)
+ utl_freebuf((void **)&p_cb->obx.p_pkt);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_ci_get_msg
+**
+** Description Proceses the get message call-in event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_ci_get_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param;
+ tBTA_MSE_CI_GET_MSG *p_ci_get_msg = &p_data->ci_get_msg;
+ UINT8 rsp_code = OBX_RSP_NOT_FOUND;
+ BOOLEAN free_pkt = TRUE, end_of_msg= TRUE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_ci_get_msg inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+ APPL_TRACE_EVENT1("status=%d",p_data->ci_get_ml_entry.status);
+#endif
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED);
+ return;
+ }
+
+ /* Process get msg call-in event if operation is still active */
+ if (p_cb->oper == BTA_MSE_OPER_GET_MSG)
+ {
+ switch (p_data->ci_get_msg.status)
+ {
+ case BTA_MA_STATUS_OK: /* Valid new entry */
+ free_pkt = FALSE;
+ p_param->frac_deliver_status = p_ci_get_msg->frac_deliver_status;
+ p_param->filled_buff_size = p_ci_get_msg->filled_buff_size;
+
+ if ( p_ci_get_msg->multi_pkt_status == BTA_MA_MPKT_STATUS_MORE)
+ {
+ p_param->byte_get_cnt += p_param->filled_buff_size;
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ else
+ rsp_code = OBX_RSP_OK;
+
+ break;
+
+ case BTA_MA_STATUS_FAIL: /* Error occurred */
+ break;
+
+ default:
+ end_of_msg = FALSE;
+ break;
+ }
+ }
+
+ if (end_of_msg)
+ bta_mse_end_of_msg(inst_idx, sess_idx,rsp_code);
+
+ if (free_pkt)
+ utl_freebuf((void **)&p_cb->obx.p_pkt);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_ci_push_msg
+**
+** Description Proceses the push message call-in event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_ci_push_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ BOOLEAN free_pkt = TRUE;
+ char handle_buf[BTA_MSE_64BIT_HEX_STR_SIZE];
+ tBTA_MA_STREAM strm;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_ci_push_msg inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+ APPL_TRACE_EVENT4(" status=%d ci_last_pkt=%d obx_final=%d oper=%d",
+ p_data->ci_push_msg.status,
+ p_data->ci_push_msg.last_packet,
+ p_obx->final_pkt,
+ p_cb->oper);
+#endif
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED);
+ return;
+ }
+
+ /* Process get msg call-in event if operation is still active */
+ if (p_cb->oper == BTA_MSE_OPER_PUSH_MSG)
+ {
+ switch (p_data->ci_push_msg.status)
+ {
+ case BTA_MA_STATUS_OK: /* Valid new entry */
+ if (p_obx->final_pkt)
+ {
+ APPL_TRACE_EVENT2("final pkt: status=%d oper=%d",
+ p_data->ci_push_msg.status, p_cb->oper);
+
+ utl_freebuf((void**)&p_obx->p_pkt);
+
+ rsp_code = OBX_RSP_OK;
+
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /* p_cb->peer_mtu */ HCI_CMD_POOL_BUF_SIZE);
+ if (p_obx->p_pkt)
+ {
+ memset(handle_buf, 0,BTA_MSE_64BIT_HEX_STR_SIZE);
+ BTA_MaInitMemStream(&strm,(UINT8 *) handle_buf, BTA_MSE_64BIT_HEX_STR_SIZE);
+ bta_ma_stream_handle(&strm, p_data->ci_push_msg.handle);
+ if (OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)handle_buf))
+ {
+ rsp_code = OBX_RSP_OK;
+ free_pkt = FALSE;
+ }
+ else
+ {
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+ else
+ {
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+ else
+ rsp_code = OBX_RSP_CONTINUE;
+ break;
+
+ case BTA_MA_STATUS_FAIL: /* Error occurred */
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (rsp_code==OBX_RSP_OK)
+ {
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+ }
+ else
+ {
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+
+
+ if (rsp_code == OBX_RSP_CONTINUE)
+ {
+ bta_mse_send_push_msg_in_prog_evt(inst_idx,sess_idx);
+ }
+ else
+ {
+ if ((rsp_code != OBX_RSP_OK) ||
+ ((p_obx->final_pkt) &&(rsp_code == OBX_RSP_OK)))
+ {
+ bta_mse_send_oper_cmpl_evt(inst_idx,sess_idx, p_data->ci_push_msg.status);
+ bta_mse_clean_push_msg(inst_idx,sess_idx);
+ }
+ }
+
+ if (free_pkt) utl_freebuf((void**)&p_obx->p_pkt);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_ci_del_msg
+**
+** Description Proceses the delete message call-in event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_ci_del_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 rsp_code = OBX_RSP_OK;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_ci_del_msg inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+ APPL_TRACE_EVENT2(" status=%d oper=%d",p_data->ci_del_msg.status, p_cb->oper);
+#endif
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ /* too late to abort now*/
+ bta_mse_abort_too_late(inst_idx,sess_idx);
+ }
+
+ /* Process get msg call-in event if operation is still active */
+ if (p_cb->oper == BTA_MSE_OPER_DEL_MSG)
+ {
+ switch (p_data->ci_del_msg.status)
+ {
+ case BTA_MA_STATUS_OK:
+ rsp_code = OBX_RSP_OK;
+ break;
+
+ case BTA_MA_STATUS_FAIL: /* Error occurred */
+ rsp_code = OBX_RSP_FORBIDDEN;
+ break;
+ default:
+ break;
+ }
+ }
+
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_mse_clean_set_msg_sts(inst_idx,sess_idx);
+
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_obx_connect
+**
+** Description Proceses the obx connect request to open a MAS session
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_obx_connect(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_MSE cback_evt_data;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_obx_connect inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+#endif
+
+ p_cb->peer_mtu = p_evt->param.conn.mtu;
+ p_cb->obx_handle = p_evt->handle;
+ memcpy(p_cb->bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN);
+
+ OBX_ConnectRsp(p_evt->handle, OBX_RSP_OK, (BT_HDR *)NULL);
+
+ /* Reset to the root directory */
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_scb->p_rootpath, p_bta_fs_cfg->max_path_len);
+
+ /* inform role manager */
+ bta_mse_pm_conn_open(p_cb->bd_addr);
+
+ bdcpy(cback_evt_data.ma_open.bd_addr, p_cb->bd_addr);
+ BCM_STRNCPY_S((char *)cback_evt_data.ma_open.dev_name, sizeof(cback_evt_data.ma_open.dev_name),
+ "", BTM_MAX_REM_BD_NAME_LEN);
+ cback_evt_data.ma_open.mas_instance_id = p_scb->mas_inst_id;
+ cback_evt_data.ma_open.mas_session_id = p_cb->obx_handle;
+
+ bta_mse_cb.p_cback(BTA_MSE_MA_OPEN_EVT, (tBTA_MSE *) &cback_evt_data);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_obx_disc
+**
+** Description Proceses the obx disconnect request to close a MAS session
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_obx_disc(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_obx_disc inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+#endif
+ rsp_code = (p_evt->obx_event == OBX_DISCONNECT_REQ_EVT) ? OBX_RSP_OK
+ : OBX_RSP_BAD_REQUEST;
+ OBX_DisconnectRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_obx_close
+**
+** Description Proceses the obx close indication to close a MAS connection
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_obx_close(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_obx_close inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+#endif
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->cout_active)
+ bta_mse_ma_sm_execute(inst_idx, sess_idx, BTA_MSE_CLOSE_CMPL_EVT, p_data);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_obx_abort
+**
+** Description Proceses the obx abort request
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_obx_abort(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("bta_mse_ma_obx_abort inst idx=%d sess idx=%d oper=%d",
+ inst_idx, sess_idx, p_cb->oper);
+#endif
+
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ switch (p_cb->oper)
+ {
+ case BTA_MSE_OPER_SETPATH:
+ case BTA_MSE_OPER_NONE:
+ OBX_AbortRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ return;
+ default:
+ break;
+
+ }
+
+ if (!p_cb->cout_active)
+ {
+ bta_mse_clean_getput(inst_idx,sess_idx, BTA_MA_STATUS_ABORTED);
+ }
+ else /* Delay the response if a call-out function is active */
+ p_cb->aborting = TRUE;
+
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_obx_put
+**
+** Description Proceses the obx put request
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_obx_put(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg;
+ tBTA_MSE_OPER_SET_MSG_STS *p_set_msg_sts = &p_cb->set_msg_sts;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ UINT16 len;
+ UINT8 *p_type;
+ UINT8 *p_param;
+ UINT8 rsp_code = OBX_RSP_OK;
+ UINT8 num_hdrs;
+ BOOLEAN free_pkt = TRUE;
+ BOOLEAN send_rsp = TRUE;
+ BOOLEAN send_ok_rsp = FALSE;
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_obx_put inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+#endif
+
+ if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len))
+ {
+ if (!memcmp(p_type, BTA_MA_HDR_TYPE_NOTIF_REG, len))
+ {
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NOTIF_REG);
+ }
+ else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG, len))
+ {
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_PUSH_MSG);
+ bta_mse_init_push_msg(inst_idx, sess_idx, &rsp_code);
+ if (rsp_code != OBX_RSP_OK)
+ {
+ OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ bta_mse_clean_push_msg(inst_idx, sess_idx);
+ return;
+ }
+ }
+ else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG_UPDATE, len))
+ {
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_UPDATE_INBOX);
+ }
+ else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG_STATUS, len))
+ {
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_SET_MSG_STATUS);
+ bta_mse_init_set_msg_sts(inst_idx, sess_idx, &rsp_code);
+ if (rsp_code != OBX_RSP_OK)
+ {
+ OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ bta_mse_clean_set_msg_sts(inst_idx, sess_idx);
+ return;
+ }
+ }
+ }
+
+ switch ( p_cb->oper)
+ {
+ case BTA_MSE_OPER_NOTIF_REG:
+
+ p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_NOTIF_STATUS, &len);
+ if (p_param)
+ {
+ p_cb->notif_reg_req.notif_status_rcv = TRUE;
+ BE_STREAM_TO_UINT8(p_cb->notif_reg_req.notif_status, p_param);
+ }
+
+ if (p_evt->param.put.final)
+ {
+ /* check end of body is included or not */
+
+ if ((num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &p_obx->offset, &p_obx->final_pkt)) &&
+ p_obx->final_pkt)
+ {
+ if (p_cb->notif_reg_req.notif_status_rcv)
+ {
+ if (!bta_mse_send_set_notif_reg(p_cb->notif_reg_req.notif_status,
+ inst_idx, sess_idx))
+ {
+ OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ }
+ else
+ {
+ /* wait for the set notif reg response from the application*/
+ break;
+ }
+ }
+ else
+ {
+ OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ }
+ }
+ else
+ {
+ OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ }
+ /* if reach here this is a bad request case so clean up*/
+ bta_mse_clean_set_notif_reg(inst_idx,sess_idx);
+ }
+ else
+ {
+ OBX_PutRsp(p_evt->handle, OBX_RSP_CONTINUE, (BT_HDR *)NULL);
+ }
+
+ break;
+ case BTA_MSE_OPER_PUSH_MSG:
+
+ if ((!p_push_msg->rcv_folder_name) &&
+ (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_push_msg->param.p_folder,
+ p_bta_mse_cfg->max_name_len)))
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("Rcv folder len=%d, name=%s ",
+ strlen( p_push_msg->param.p_folder),
+ p_push_msg->param.p_folder);
+#endif
+ p_push_msg->rcv_folder_name = TRUE;
+ }
+
+ if (!p_push_msg->rcv_charset)
+ {
+ p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_CHARSET, &len);
+ if (p_param)
+ {
+
+ p_push_msg->rcv_charset = TRUE;
+ BE_STREAM_TO_UINT8(p_push_msg->param.charset, p_param);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("Rcv Charset=%d(0-native 1-UTF8)",p_push_msg->param.charset);
+#endif
+ }
+ }
+
+ if (!p_push_msg->rcv_transparent)
+ {
+ p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_TRANSPARENT, &len);
+ if (p_param)
+ {
+ p_push_msg->rcv_transparent = TRUE;
+ BE_STREAM_TO_UINT8(p_push_msg->param.transparent, p_param);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("Rcv Transparent=%d",p_push_msg->param.transparent);
+#endif
+ }
+ }
+
+ if (!p_push_msg->rcv_retry)
+ {
+ p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_RETRY, &len);
+ if (p_param)
+ {
+ p_push_msg->rcv_retry = TRUE;
+ BE_STREAM_TO_UINT8(p_push_msg->param.retry, p_param);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("Rcv Retry=%d",p_push_msg->param.retry);
+#endif
+ }
+ }
+
+ /* Read the body header from the obx packet */
+ num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &p_obx->offset,
+ &p_obx->final_pkt);
+ /* process body or end of body header */
+ if (num_hdrs >= 1 )
+ {
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("Rcv Body or EndOfBody body_hdr=%d len=%d final=%d",
+ num_hdrs,
+ p_obx->offset,
+ p_obx->final_pkt);
+#endif
+
+ if (p_push_msg->rcv_charset && p_push_msg->rcv_folder_name)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("Rcv all Required params");
+#endif
+
+ free_pkt = FALSE;
+ p_obx->p_pkt = p_evt->p_pkt;
+ if (p_push_msg->first_req_pkt)
+ {
+ p_push_msg->first_req_pkt = FALSE;
+ bta_mse_req_app_access( inst_idx, sess_idx, p_data);
+ }
+ else
+ {
+ bta_mse_pushmsg(inst_idx, sess_idx, FALSE);
+ }
+ send_rsp = FALSE;
+ }
+ else
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_ERROR0("Not all Mandatory params are rcv before body/EndofBody: bad request");
+#endif
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ }
+ else
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("No Body or End of Body in this push msg pkt");
+#endif
+ }
+
+ if (!p_obx->final_pkt)
+ {
+ if (rsp_code != OBX_RSP_BAD_REQUEST)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("Not a final pkt and no error set rsp_code=Continue");
+#endif
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ }
+
+ if (send_rsp) OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ if (rsp_code == OBX_RSP_BAD_REQUEST )
+ {
+ if (!p_push_msg->first_req_pkt)
+ bta_mse_send_oper_cmpl_evt(inst_idx,sess_idx, BTA_MA_STATUS_FAIL);
+ bta_mse_clean_push_msg(inst_idx,sess_idx);
+ }
+ break;
+ case BTA_MSE_OPER_UPDATE_INBOX:
+
+ if (p_evt->param.put.final)
+ {
+ /* check enod of body is included or not */
+
+ if ((num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &p_obx->offset, &p_obx->final_pkt)) &&
+ p_obx->final_pkt)
+ {
+
+ mas_session_id = (tBTA_MA_SESS_HANDLE) p_cb->obx_handle;
+ bta_mse_cb.p_cback(BTA_MSE_UPDATE_INBOX_EVT, (tBTA_MSE *)&mas_session_id);
+ }
+ else
+ {
+ OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ }
+ }
+ else
+ {
+ OBX_PutRsp(p_evt->handle, OBX_RSP_CONTINUE, (BT_HDR *)NULL);
+ }
+
+
+ break;
+ case BTA_MSE_OPER_SET_MSG_STATUS:
+
+
+ if ((!p_set_msg_sts->rcv_msg_handle) &&
+ (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_set_msg_sts->p_msg_handle,
+ BTA_MSE_64BIT_HEX_STR_SIZE)))
+ {
+ bta_ma_convert_hex_str_to_64bit_handle(p_set_msg_sts->p_msg_handle,
+ p_set_msg_sts->handle);
+ p_set_msg_sts->rcv_msg_handle = TRUE;
+ }
+
+ if (!p_set_msg_sts->rcv_sts_ind)
+ {
+ p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_STS_INDCTR, &len);
+ if (p_param)
+ {
+ p_set_msg_sts->rcv_sts_ind = TRUE;
+ BE_STREAM_TO_UINT8(p_set_msg_sts->sts_ind, p_param);
+ }
+ }
+
+ if (!p_set_msg_sts->rcv_sts_val)
+ {
+ p_param = bta_mse_read_app_params(p_evt->p_pkt, BTA_MA_APH_STS_VALUE, &len);
+ if (p_param)
+ {
+ p_set_msg_sts->rcv_sts_val = TRUE;
+ BE_STREAM_TO_UINT8(p_set_msg_sts->sts_val, p_param);
+ }
+ }
+
+ /* Read the body header from the obx packet */
+ num_hdrs = OBX_ReadBodyHdr(p_evt->p_pkt, &p_obx->p_start, &p_obx->offset,
+ &p_obx->final_pkt);
+ /* process body or end of body header */
+ if ((num_hdrs >= 1 && p_obx->final_pkt ) )
+ {
+ if (p_set_msg_sts->rcv_msg_handle && p_set_msg_sts->rcv_sts_ind &&
+ p_set_msg_sts->rcv_sts_val)
+ {
+ if (p_set_msg_sts->sts_ind == BTA_MA_STS_INDTR_DELETE)
+ {
+ p_cb->oper = BTA_MSE_OPER_DEL_MSG;
+ bta_mse_req_app_access( inst_idx, sess_idx, p_data);
+ }
+ else
+ {
+ if (bta_mse_co_set_msg_read_status((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ p_set_msg_sts->handle,
+ p_set_msg_sts->sts_val,
+ bta_mse_cb.app_id) != BTA_MA_STATUS_OK)
+ {
+ rsp_code = OBX_RSP_FORBIDDEN;
+ }
+ send_ok_rsp = TRUE;
+ }
+ }
+ else
+ {
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ }
+
+ if (!p_obx->final_pkt)
+ {
+ if (rsp_code != OBX_RSP_BAD_REQUEST)
+ {
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ }
+
+ if (rsp_code != OBX_RSP_OK)
+ {
+ OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ if (rsp_code == OBX_RSP_BAD_REQUEST )
+ {
+ bta_mse_clean_set_msg_sts(inst_idx,sess_idx);
+ }
+ }
+ else
+ {
+ if (send_ok_rsp)
+ {
+ OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ bta_mse_clean_set_msg_sts(inst_idx,sess_idx);
+ }
+ }
+ break;
+ default:
+ OBX_PutRsp(p_evt->handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ break;
+ }
+
+ /* Done with Obex packet */
+ if (free_pkt) utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_obx_get
+**
+** Description Proceses the obx get request
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_obx_get(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+ UINT16 len;
+ UINT8 *p_type;
+ tBTA_MSE_MA_GET_ACT get_act = BTA_MSE_MA_GET_ACT_NONE;
+ tBTA_MSE_MA_GET_TYPE get_type = BTA_MSE_MA_GET_TYPE_NONE;
+ UINT8 rsp_code = OBX_RSP_BAD_REQUEST;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_obx_get inst idx=%d sess idx=%d",inst_idx, sess_idx);
+ APPL_TRACE_EVENT1(" oper=%d",p_cb->oper );
+#endif
+ switch (p_cb->oper)
+ {
+ case BTA_MSE_OPER_GET_FOLDER_LIST:
+ get_type = BTA_MSE_MA_GET_TYPE_CON_FOLDER_LIST;
+ break;
+ case BTA_MSE_OPER_GET_MSG_LIST:
+ get_type = BTA_MSE_MA_GET_TYPE_CON_MSG_LIST;
+ break;
+ case BTA_MSE_OPER_GET_MSG:
+ get_type = BTA_MSE_MA_GET_TYPE_CON_MSG;
+ break;
+ case BTA_MSE_OPER_NONE:
+ if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len))
+ {
+ if (!memcmp(p_type, BTA_MA_HDR_TYPE_FOLDER_LIST, len))
+ {
+ get_type = BTA_MSE_MA_GET_TYPE_FOLDER_LIST;
+ }
+ else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG_LIST, len) )
+ {
+ get_type = BTA_MSE_MA_GET_TYPE_MSG_LIST;
+ }
+ else if (!memcmp(p_type, BTA_MA_HDR_TYPE_MSG, len) )
+ {
+
+ get_type = BTA_MSE_MA_GET_TYPE_MSG;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_ma_obx_get get_type=%d",get_type);
+#endif
+ switch (get_type)
+ {
+ case BTA_MSE_MA_GET_TYPE_FOLDER_LIST:
+ bta_mse_ma_fl_read_app_params(inst_idx, sess_idx, p_evt->p_pkt);
+ get_act = BTA_MSE_MA_GET_ACT_NEW_FOLDER_LIST;
+ break;
+
+ case BTA_MSE_MA_GET_TYPE_MSG_LIST:
+ if (!p_cb->ml_param.p_name)
+ {
+ p_cb->ml_param.p_name = (char *)GKI_getbuf((UINT16)(p_bta_mse_cfg->max_name_len + 1));
+ }
+
+ if (!p_cb->ml_param.p_path)
+ {
+ p_cb->ml_param.p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1));
+ }
+
+ if ((p_cb->ml_param.p_name != NULL) && (p_cb->ml_param.p_path != NULL))
+ {
+ if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->ml_param.p_name,
+ p_bta_mse_cfg->max_name_len))
+ {
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ break;
+ }
+ else
+ {
+ if (!bta_mse_get_msglist_path(inst_idx, sess_idx))
+ {
+ rsp_code = OBX_RSP_NOT_FOUND;
+ break;
+ }
+ }
+ }
+ else
+ {
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ break;
+ }
+
+ bta_mse_ma_ml_read_app_params(inst_idx, sess_idx,p_evt->p_pkt);
+ get_act = BTA_MSE_MA_GET_ACT_NEW_MSG_LIST;
+ break;
+
+ case BTA_MSE_MA_GET_TYPE_MSG:
+
+ if (!p_cb->msg_param.p_msg_handle)
+ {
+ if ((p_cb->msg_param.p_msg_handle = (char *)GKI_getbuf((UINT16)(BTA_MSE_64BIT_HEX_STR_SIZE))) == NULL )
+ {
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ get_act = BTA_MSE_MA_GET_ACT_ERR;
+ break;
+ }
+ }
+
+ if (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->msg_param.p_msg_handle,
+ BTA_MSE_64BIT_HEX_STR_SIZE))
+ {
+ bta_ma_convert_hex_str_to_64bit_handle(p_cb->msg_param.p_msg_handle,
+ p_cb->msg_param.data.handle);
+ }
+ else
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("Unable to decode or find Name Header for Message Handle");
+#endif
+
+ get_act = BTA_MSE_MA_GET_ACT_ERR;
+ break;
+ }
+
+ if (!bta_mse_ma_msg_read_app_params(inst_idx, sess_idx, p_evt->p_pkt))
+ {
+ get_act = BTA_MSE_MA_GET_ACT_ERR;
+ break;
+ }
+ get_act = BTA_MSE_MA_GET_ACT_NEW_MSG;
+ break;
+
+ case BTA_MSE_MA_GET_TYPE_CON_FOLDER_LIST:
+ get_act = BTA_MSE_MA_GET_ACT_CON_FOLDER_LIST;
+ break;
+
+ case BTA_MSE_MA_GET_TYPE_CON_MSG_LIST:
+ get_act = BTA_MSE_MA_GET_ACT_CON_MSG_LIST;
+ break;
+
+ case BTA_MSE_MA_GET_TYPE_CON_MSG:
+ get_act = BTA_MSE_MA_GET_ACT_CON_MSG;
+ break;
+ default:
+ break;
+ }
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1(" get_act=%d",get_act);
+#endif
+ switch (get_act)
+ {
+ case BTA_MSE_MA_GET_ACT_NEW_FOLDER_LIST:
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_GET_FOLDER_LIST);
+ bta_mse_getfolderlist(inst_idx,sess_idx, TRUE);
+ break;
+ case BTA_MSE_MA_GET_ACT_CON_FOLDER_LIST:
+ bta_mse_getfolderlist(inst_idx,sess_idx, FALSE);
+ break;
+
+ case BTA_MSE_MA_GET_ACT_NEW_MSG_LIST:
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_GET_MSG_LIST);
+ bta_mse_req_app_access( inst_idx, sess_idx, p_data);
+ break;
+ case BTA_MSE_MA_GET_ACT_CON_MSG_LIST:
+ bta_mse_getmsglist(inst_idx,sess_idx, FALSE);
+ break;
+
+ case BTA_MSE_MA_GET_ACT_NEW_MSG:
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_GET_MSG);
+ if (p_cb->msg_param.data.fraction_request == BTA_MA_FRAC_REQ_FIRST ||
+ p_cb->msg_param.data.fraction_request == BTA_MA_FRAC_REQ_NEXT)
+ {
+ p_cb->msg_param.add_frac_del_hdr = TRUE;
+ }
+ p_cb->msg_param.byte_get_cnt = 0;
+ bta_mse_req_app_access( inst_idx, sess_idx, p_data);
+ break;
+ case BTA_MSE_MA_GET_ACT_CON_MSG:
+ bta_mse_getmsg(inst_idx,sess_idx, FALSE);
+ break;
+
+ case BTA_MSE_MA_GET_ACT_ERR:
+ default:
+ OBX_GetRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ utl_freebuf((void**)&p_cb->ml_param.p_name);
+ utl_freebuf((void**)&p_cb->ml_param.p_path);
+ break;
+ }
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_obx_setpath
+**
+** Description Proceses the obx setpath request
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_obx_setpath(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_MA_DIR_NAV flags = (tBTA_MA_DIR_NAV)p_evt->param.sp.flag;
+ UINT8 rsp_code = OBX_RSP_BAD_REQUEST;
+ tBTA_MSE_OPER mse_oper = BTA_MSE_OPER_NONE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_obx_setpath inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+ APPL_TRACE_EVENT1(" flags=%d ", flags);
+#endif
+
+ /* Verify flags and handle before accepting */
+ if ((flags == BTA_MA_DIR_NAV_ROOT_OR_DOWN_ONE_LVL) ||
+ (flags == BTA_MA_DIR_NAV_UP_ONE_LVL))
+ {
+
+ p_cb->sp.p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1));
+ p_cb->sp.p_name = (char *)GKI_getbuf((UINT16)(p_bta_mse_cfg->max_name_len + 1));
+ if (p_cb->sp.p_name != NULL )
+ {
+ p_cb->sp.flags = flags;
+
+ if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->sp.p_name,
+ p_bta_fs_cfg->max_path_len))
+ {
+ p_cb->sp.p_name[0] = '\0';
+ }
+
+ rsp_code = bta_mse_chdir( inst_idx, sess_idx, &mse_oper);
+
+ }
+ else
+ {
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+
+ bta_mse_set_ma_oper(inst_idx, sess_idx, mse_oper);
+ if (mse_oper != BTA_MSE_OPER_NONE)
+ {
+ bta_mse_req_app_access( inst_idx, sess_idx, p_data);
+ }
+ else
+ {
+ OBX_SetPathRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ utl_freebuf((void**)&p_cb->sp.p_name);
+ }
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_conn_err_rsp
+**
+** Description Proceses the inavlid obx connection request
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_conn_err_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_conn_err_rsp inst idx=%d sess idx=%d",inst_idx, sess_idx);
+#endif
+
+ OBX_ConnectRsp(p_data->obx_evt.handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ /* Done with Obex packet */
+ utl_freebuf((void**)&(p_data->obx_evt.p_pkt));
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_close_complete
+**
+** Description Proceses the connection close complete event.
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_close_complete(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE cback_evt_data;
+ tBTA_MSE *p_cevt = &cback_evt_data;
+ UINT8 num_act_mas=0, num_act_sess=0, i;
+ tBTA_MA_STATUS clean_getput_status = BTA_MA_STATUS_OK;
+ UINT8 ccb_idx;
+ BD_ADDR bd_addr;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ma_close_complete inst idx=%d sess idx=%d",inst_idx, sess_idx);
+#endif
+
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting) clean_getput_status = BTA_MA_STATUS_ABORTED;
+ bta_mse_clean_getput(inst_idx, sess_idx, clean_getput_status);
+ utl_freebuf((void**)&p_cb->p_workdir);
+
+ /* inform role manager */
+
+ bta_mse_pm_conn_close(p_cb->bd_addr);
+ bdcpy(bd_addr, p_cb->bd_addr);
+ memset(p_cb->bd_addr, 0, BD_ADDR_LEN);
+ p_cb->peer_mtu = 0;
+
+ /* We now done with the close this seesion so issue a BTA_MSE_MA_CLOSE_EVT*/
+ p_cevt->ma_close.mas_session_id = p_cb->obx_handle;
+ p_cevt->ma_close.mas_instance_id = p_scb->mas_inst_id;
+ p_cevt->ma_close.status = BTA_MA_STATUS_OK ;
+ bta_mse_cb.p_cback(BTA_MSE_MA_CLOSE_EVT, (tBTA_MSE *) p_cevt);
+
+
+ /* turn off the registration status for the associated MAs instance
+ and also check whether MN connection needs to be closed or not */
+ if (bta_mse_find_bd_addr_match_mn_cb_index(bd_addr, &ccb_idx) &&
+ bta_mse_mn_is_inst_id_exist(ccb_idx, p_scb->mas_inst_id))
+ {
+ bta_mse_mn_remove_inst_id(ccb_idx, p_scb->mas_inst_id);
+ if (!bta_mse_mn_find_num_of_act_inst_id(ccb_idx))
+ {
+ bta_mse_mn_sm_execute(ccb_idx,BTA_MSE_MN_INT_CLOSE_EVT, NULL);
+ }
+ }
+
+ /* Check Any MAS instance need to be stopped */
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("stopping=%d MAS in use=%d", p_scb->stopping,p_scb->in_use);
+#endif
+ if (p_scb->stopping && p_scb->in_use)
+ {
+ num_act_sess = 0;
+ for (i=0; i < BTA_MSE_NUM_SESS; i ++)
+ {
+ p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, i);
+ if (p_cb->state != BTA_MSE_MA_LISTEN_ST)
+ num_act_sess++;
+ }
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("num_act_sess=%d ", num_act_sess);
+#endif
+ if (!num_act_sess)
+ {
+ p_cevt->stop.status = BTA_MA_STATUS_OK;
+ p_cevt->stop.mas_instance_id = p_scb->mas_inst_id;
+ bta_mse_cb.p_cback(BTA_MSE_STOP_EVT, (tBTA_MSE *) p_cevt);
+ bta_mse_clean_mas_service(inst_idx);
+ }
+ }
+
+ if (bta_mse_cb.disabling && bta_mse_cb.enable)
+ {
+ num_act_mas=0;
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ p_scb = BTA_MSE_GET_INST_CB_PTR(i);
+ if (p_scb->in_use )
+ num_act_mas++;
+ }
+
+ if (!num_act_mas)
+ {
+ bta_mse_cb.enable = FALSE;
+ p_cevt->disable.status = BTA_MA_STATUS_OK;
+ p_cevt->disable.app_id = bta_mse_cb.app_id;
+ bta_mse_cb.p_cback(BTA_MSE_DISABLE_EVT, (tBTA_MSE *) p_cevt);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("MSE Disabled location-2");
+#endif
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ignore_obx
+**
+** Description Ignores the obx event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ignore_obx(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ignore_obx inst idx=%d sess idx=%d",inst_idx, sess_idx);
+#endif
+
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_obx_cback
+**
+** Description OBX callback function for MA.
+**
+** Parameters handle - Handle for Obex session
+** obx_event - Obex event
+** param - event parameters
+** p_pkt - pointer to Obex packet
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_MSE_OBX_EVT *p_obx_msg;
+ UINT16 event = 0;
+
+ switch (obx_event)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ event = BTA_MSE_MA_OBX_CONN_EVT;
+ break;
+ case OBX_DISCONNECT_REQ_EVT:
+ event = BTA_MSE_MA_OBX_DISC_EVT;
+ break;
+ case OBX_PUT_REQ_EVT:
+ event = BTA_MSE_MA_OBX_PUT_EVT;
+ break;
+ case OBX_GET_REQ_EVT:
+ event = BTA_MSE_MA_OBX_GET_EVT;
+ break;
+ case OBX_SETPATH_REQ_EVT:
+ event = BTA_MSE_MA_OBX_SETPATH_EVT;
+ break;
+ case OBX_ABORT_REQ_EVT:
+ event = BTA_MSE_MA_OBX_ABORT_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_MSE_MA_OBX_CLOSE_EVT;
+ break;
+ case OBX_TIMEOUT_EVT:
+ break;
+ case OBX_PASSWORD_EVT:
+ break;
+ default:
+ /* Unrecognized packet; disconnect the session */
+ if (p_pkt)
+ event = BTA_MSE_MA_OBX_DISC_EVT;
+ }
+
+ /* send event to BTA, if any */
+ if (event && (p_obx_msg =
+ (tBTA_MSE_OBX_EVT *) GKI_getbuf(sizeof(tBTA_MSE_OBX_EVT))) != NULL)
+ {
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ APPL_TRACE_DEBUG1("MA OBX Event Callback: mse_obx_event [%s]", bta_mse_obx_evt_code(event));
+#endif
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+ p_obx_msg->hdr.layer_specific = 0xFFFF;
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+/*******************************************************************************
+** Message Notification Client (MNC) Action functions
+**
+*******************************************************************************/
+/******************************************************************************
+**
+** Function bta_mse_mn_sdp_cback
+**
+** Description This is the SDP callback function used by MSE.
+** 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.
+**
+** Parameters ccb_idx - Index to the MN control block
+** status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_mse_mn_sdp_cback(UINT8 ccb_idx, UINT16 status)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE_MN_SDP_OK *p_buf;
+ tSDP_DISC_REC *p_rec = NULL;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT8 scn = 0;
+ BOOLEAN found = FALSE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_sdp_cback status:%d", status);
+#endif
+ if (status == SDP_SUCCESS || status == SDP_DB_FULL)
+ {
+ /* loop through all records we found */
+ do
+ {
+ /* get next record; if none found, we're done */
+ if ((p_rec = SDP_FindServiceInDb(p_cb->p_db, p_cb->sdp_service,
+ p_rec)) == NULL)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("SDP Not Found");
+#endif
+ break;
+ }
+
+ /* get scn from proto desc list; if not found, go to next record */
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ found = TRUE;
+ scn = (UINT8) pe.params[0];
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("SDP found scn=%d", scn);
+#endif
+ /* we've got everything, we're done */
+ break;
+ }
+ else
+ continue;
+ } while (TRUE);
+ }
+
+ /* send result in event back to BTA */
+ if ((p_buf = (tBTA_MSE_MN_SDP_OK *) GKI_getbuf(sizeof(tBTA_MSE_MN_SDP_OK))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_MN_SDP_FAIL_EVT;
+ p_buf->ccb_idx = ccb_idx;
+ if (status == SDP_SUCCESS || status == SDP_DB_FULL)
+ {
+ if (found == TRUE)
+ {
+ p_buf->hdr.event = BTA_MSE_MN_SDP_OK_EVT;
+ p_buf->scn = scn;
+ }
+ else
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("SDP 1 BTA_MSE_MN_SDP_FAIL_EVT");
+#endif
+ }
+ }
+ else
+ {
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("SDP 2 BTA_MSE_MN_SDP_FAIL_EVT");
+#endif
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/******************************************************************************
+**
+** Function bta_mse_mn_sdp_cback0
+**
+** Description This is the SDP callback function used by MN indx = 0
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_mse_mn_sdp_cback0(UINT16 status)
+{
+ bta_mse_mn_sdp_cback(0, status);
+}
+
+/******************************************************************************
+**
+** Function bta_mse_mn_sdp_cback1
+**
+** Description This is the SDP callback function used by MN indx = 1
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_mse_mn_sdp_cback1(UINT16 status)
+{
+ bta_mse_mn_sdp_cback(1, status);
+}
+
+/******************************************************************************
+**
+** Function bta_mse_mn_sdp_cback2
+**
+** Description This is the SDP callback function used by MN indx = 2
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_mse_mn_sdp_cback2(UINT16 status)
+{
+ bta_mse_mn_sdp_cback(2, status);
+}
+
+/******************************************************************************
+**
+** Function bta_mse_mn_sdp_cback3
+**
+** Description This is the SDP callback function used by MN indx = 3
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_mse_mn_sdp_cback3(UINT16 status)
+{
+ bta_mse_mn_sdp_cback(3, status);
+}
+
+/******************************************************************************
+**
+** Function bta_mse_mn_sdp_cback4
+**
+** Description This is the SDP callback function used by MN indx = 4
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_mse_mn_sdp_cback4(UINT16 status)
+{
+ bta_mse_mn_sdp_cback(4, status);
+}
+
+/******************************************************************************
+**
+** Function bta_mse_mn_sdp_cback5
+**
+** Description This is the SDP callback function used by MN indx = 5
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_mse_mn_sdp_cback5(UINT16 status)
+{
+ bta_mse_mn_sdp_cback(5, status);
+}
+
+/******************************************************************************
+**
+** Function bta_mse_mn_sdp_cback6
+**
+** Description This is the SDP callback function used by MN indx = 6
+**
+** Parameters status - status of the SDP callabck
+**
+** Returns void.
+**
+******************************************************************************/
+static void bta_mse_mn_sdp_cback6(UINT16 status)
+{
+ bta_mse_mn_sdp_cback(6, status);
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_init_sdp
+**
+** Description Initialize SDP on message notification server device.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_init_sdp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = &(bta_mse_cb.ccb[ccb_idx]);
+ tBTA_MSE_MN_INT_OPEN *p_evt = &p_data->mn_int_open;
+
+ tSDP_UUID uuid_list;
+ UINT16 attr_list[3];
+ UINT16 num_attrs = 2;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_mn_init_sdp");
+#endif
+
+ p_cb->in_use = TRUE;
+ p_cb->sec_mask = p_evt->sec_mask;
+ bdcpy(p_cb->bd_addr,p_evt->bd_addr);
+ p_cb->sdp_pending = TRUE;
+ p_cb->sdp_cback = bta_mse_mn_sdp_cback_arr[ccb_idx];
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT6("SDP INIT BD_ADDR= %x:%x:%x:%x:%x:%x",
+ p_cb->bd_addr[0],
+ p_cb->bd_addr[1],
+ p_cb->bd_addr[2],
+ p_cb->bd_addr[3],
+ p_cb->bd_addr[4],
+ p_cb->bd_addr[5]);
+#endif
+
+ if ((p_cb->p_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_MSE_MN_DISC_SIZE)) != NULL)
+ {
+ attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+ attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+
+ uuid_list.len = LEN_UUID_16;
+
+ p_cb->sdp_service = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
+ uuid_list.uu.uuid16 = UUID_SERVCLASS_MESSAGE_NOTIFICATION;
+
+ SDP_InitDiscoveryDb(p_cb->p_db, BTA_MSE_MN_DISC_SIZE, 1, &uuid_list, num_attrs, attr_list);
+ if (!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db, p_cb->sdp_cback))
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("SDP Init failed ");
+#endif
+ bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_SDP_FAIL_EVT, p_data);
+ }
+ else
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("SDP Init Success ");
+#endif
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_start_client
+**
+** Description Starts the OBEX client for Message Notification service.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_start_client(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ BOOLEAN connect_fail = TRUE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_start_client ccb idx=%d ",ccb_idx);
+#endif
+
+ /* free discovery data base */
+ utl_freebuf((void**)&p_cb->p_db);
+ p_cb->sdp_pending = FALSE;
+ /* Allocate an OBX packet */
+ if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(OBX_HANDLE_NULL, OBX_CMD_POOL_SIZE)) != NULL)
+ {
+ /* set security level */
+ BTM_SetSecurityLevel (TRUE, "BTA_MNC", BTM_SEC_SERVICE_MAP,
+ p_cb->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, p_data->mn_sdp_ok.scn);
+
+ if (p_cb->sdp_service == UUID_SERVCLASS_MESSAGE_NOTIFICATION)
+ {
+ OBX_AddTargetHdr(p_obx->p_pkt, (UINT8 *)BTA_MAS_MESSAGE_NOTIFICATION_TARGET_UUID,
+ BTA_MAS_UUID_LENGTH);
+ }
+ if (OBX_ConnectReq(p_cb->bd_addr, p_data->mn_sdp_ok.scn, OBX_MAX_MTU,
+ bta_mse_mn_obx_cback, &p_cb->obx_handle, p_obx->p_pkt) == OBX_SUCCESS)
+ {
+ p_obx->p_pkt = NULL; /* OBX will free the memory */
+ connect_fail = FALSE;
+ }
+ else
+ {
+ utl_freebuf((void**)&p_obx->p_pkt);
+ }
+ }
+
+ if (connect_fail)
+ {
+ bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_OBX_CLOSE_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_rsp_timeout
+**
+** Description Process the OBX response timeout event
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_rsp_timeout(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+ if (p_cb->timer_oper == BTA_MSE_TIMER_OP_ABORT)
+ {
+ /* Start stop response timer */
+ bta_mse_mn_start_timer(ccb_idx, BTA_MSE_TIMER_OP_STOP);
+
+ OBX_DisconnectReq(p_cb->obx_handle, NULL);
+ }
+ else /* Timeout waiting for disconnect response */
+ {
+ bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_OBX_CLOSE_EVT, p_data);
+
+ }
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_stop_client
+**
+** Description Stop the OBX client for Message Notification service.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_stop_client(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_stop_client ccb idx=%d ",ccb_idx);
+#endif
+
+ if (!p_cb->sdp_pending)
+ {
+ /* Start stop response timer */
+ bta_mse_mn_start_timer(ccb_idx, BTA_MSE_TIMER_OP_STOP);
+ OBX_DisconnectReq(p_cb->obx_handle, NULL);
+ }
+ else
+ {
+ APPL_TRACE_WARNING0("bta_mase_mn_stop_client: Waiting for SDP to complete");
+ }
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_obx_conn_rsp
+**
+** Description Process OBX connection response.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_obx_conn_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_MSE param;
+ UINT8 mas_insatnce_id;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_obx_conn_rsp ccb idx=%d ",ccb_idx);
+#endif
+
+ p_cb->peer_mtu = p_data->obx_evt.param.conn.mtu;
+ p_cb->obx_handle = p_evt->handle;
+
+ if (p_cb->sdp_service == UUID_SERVCLASS_MESSAGE_NOTIFICATION)
+ {
+ bdcpy(param.mn_open.bd_addr ,p_cb->bd_addr);
+ BCM_STRNCPY_S((char *)param.mn_open.dev_name, sizeof(param.mn_open.dev_name), "",
+ BTM_MAX_REM_BD_NAME_LEN);
+ if (bta_mse_mn_get_first_inst_id(ccb_idx, &mas_insatnce_id))
+ {
+ param.mn_open.first_mas_instance_id = mas_insatnce_id;
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("Unable to find the first instance ID");
+ }
+ }
+
+ /* inform role manager */
+ bta_mse_pm_conn_open(p_cb->bd_addr);
+
+ bta_mse_cb.p_cback(BTA_MSE_MN_OPEN_EVT, &param);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_close
+**
+** Description Process the connection close event.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_close(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_close ccb idx=%d ",ccb_idx);
+#endif
+
+ bta_mse_mn_remove_all_inst_ids(ccb_idx);
+
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->sdp_pending && !p_cb->cout_active)
+ bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_CLOSE_CMPL_EVT, p_data);
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_send_notif
+**
+** Description Process send notification request
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_send_notif(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE_MN_API_SEND_NOTIF *p_evt = &p_data->mn_send_notif;
+ UINT8 *p_buffer;
+ UINT16 buffer_len;
+ tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL;
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_send_notif ccb_idx=%d ",ccb_idx);
+#endif
+
+ if ( (p_cb->req_pending == TRUE) &&
+ (p_cb->obx_oper == BTA_MSE_MN_OP_PUT_EVT_RPT))
+ {
+ /* only one pending request per Obex connection is allowed */
+ bta_mse_mn_send_notif_evt(p_evt->mas_instance_id,
+ BTA_MA_STATUS_NO_RESOURCE,
+ p_cb->bd_addr);
+ return;
+ }
+
+ memset(&(p_cb->msg_notif), 0, sizeof(tBTA_MSE_MN_MSG_NOTIF));
+
+ if ((p_buffer = (UINT8 *)GKI_getbuf(BTA_MSE_MN_MAX_MSG_EVT_OBECT_SIZE)) != NULL)
+ {
+ /* Build the Message Event Object */
+ buffer_len = BTA_MSE_MN_MAX_MSG_EVT_OBECT_SIZE;
+ status = bta_mse_build_map_event_rpt_obj( p_evt->notif_type,
+ p_evt->handle,
+ p_evt->p_folder,
+ p_evt->p_old_folder,
+ p_evt->msg_type,
+ &buffer_len,
+ p_buffer);
+ if (status == BTA_MA_STATUS_OK)
+ {
+ p_cb->msg_notif.p_buffer = p_buffer;
+ p_cb->msg_notif.buffer_len = buffer_len;
+ p_cb->msg_notif.bytes_sent = 0;
+ p_cb->msg_notif.mas_instance_id = p_evt->mas_instance_id;
+ status = bta_mse_mn_cont_send_notif(ccb_idx, TRUE);
+ }
+ }
+
+ if ( status != BTA_MA_STATUS_OK)
+ {
+ bta_mse_mn_send_notif_evt(p_evt->mas_instance_id,
+ BTA_MA_STATUS_NO_RESOURCE,
+ p_cb->bd_addr);
+ bta_mse_mn_clean_send_notif(ccb_idx);
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("status=%d ",status );
+#endif
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_put_rsp
+**
+** Description Process the obx PUT response.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_put_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_MSE_MN_MSG_NOTIF *p_msg_notif = &p_cb->msg_notif;
+ tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_mn_put_rsp ccb idx=%d rsp_code=%d",
+ ccb_idx, p_evt->rsp_code);
+#endif
+
+ p_cb->req_pending = FALSE;
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (p_cb->obx_oper == BTA_MSE_MN_OP_PUT_EVT_RPT)
+ {
+ /* If not finished with Put, start another read */
+ if (p_evt->rsp_code == OBX_RSP_CONTINUE)
+ bta_mse_mn_cont_send_notif(ccb_idx, FALSE);
+ else
+ {
+ /* done with obex operation */
+ if ( p_evt->rsp_code == OBX_RSP_OK ) status = BTA_MA_STATUS_OK;
+ bta_mse_mn_send_notif_evt(p_msg_notif->mas_instance_id, status,
+ p_cb->bd_addr);
+ bta_mse_mn_clean_send_notif(ccb_idx);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_close_compl
+**
+** Description Process the close complete event.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_close_compl(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE param;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_close_compl ccb idx=%d ",ccb_idx);
+#endif
+
+ /* free discovery data base */
+ utl_freebuf((void**)&p_cb->p_db);
+ p_cb->sdp_pending = FALSE;
+
+ p_cb->cout_active = FALSE;
+ bta_mse_mn_stop_timer(ccb_idx, BTA_MSE_TIMER_OP_ALL);
+ bta_mse_mn_clean_send_notif(ccb_idx);
+ /* inform role manager */
+ bta_mse_pm_conn_close(p_cb->bd_addr);
+ bdcpy(param.mn_close.bd_addr ,p_cb->bd_addr);
+ bta_mse_cb.p_cback(BTA_MSE_MN_CLOSE_EVT, &param);
+ memset(p_cb, 0 , sizeof(tBTA_MSE_MN_CB));
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_abort
+**
+** Description Process the abort event.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_abort(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_abort ccb idx=%d ",ccb_idx);
+#endif
+ /* Abort an active request */
+ if (p_cb->obx_oper != BTA_MSE_MN_OP_NONE)
+ {
+ p_cb->aborting = BTA_MSE_MN_ABORT_REQ_NOT_SENT;
+
+ /* Issue the abort request only if no request pending.
+ * some devices do not like out of sequence aborts even though
+ * the spec allows it */
+ if (!p_cb->req_pending)
+ {
+ /* Start abort response timer */
+ bta_mse_mn_start_timer(ccb_idx, BTA_MSE_TIMER_OP_ABORT);
+ OBX_AbortReq(p_cb->obx_handle, (BT_HDR *)NULL);
+ p_cb->aborting = BTA_MSE_MN_ABORT_REQ_SENT;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_abort_rsp
+**
+** Description Process the abort response event.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_abort_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_MSE_MN_MSG_NOTIF *p_msg_notif = &p_cb->msg_notif;
+ tBTA_MA_STATUS status = BTA_MA_STATUS_FAIL;
+
+
+ bta_mse_mn_stop_timer(ccb_idx,BTA_MSE_TIMER_OP_ABORT);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (p_cb->obx_oper != BTA_MSE_MN_OP_NONE)
+ {
+ if (p_cb->obx_oper == BTA_MSE_MN_OP_PUT_EVT_RPT )
+ {
+ bta_mse_mn_send_notif_evt(p_msg_notif->mas_instance_id, status,
+ p_cb->bd_addr);
+ bta_mse_mn_clean_send_notif(ccb_idx);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_sdp_fail
+**
+** Description Process the SDP fail event.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_sdp_fail(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_sdp_fail ccb idx=%d ",ccb_idx);
+#endif
+ /* free discovery data base */
+ utl_freebuf((void**)&p_cb->p_db);
+ p_cb->sdp_pending = FALSE;
+ bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_OBX_CLOSE_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_obx_tout
+**
+** Description Process the obx timeout event.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_obx_tout(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_obx_tout ccb idx=%d ",ccb_idx);
+#endif
+
+ if (p_cb->req_pending)
+ {
+ if (p_cb->obx_oper == BTA_MSE_MN_OP_PUT_EVT_RPT)
+ {
+ bta_mse_mn_send_notif_evt( p_cb->msg_notif.mas_instance_id,
+ BTA_MA_STATUS_FAIL,
+ p_cb->bd_addr);
+ bta_mse_mn_clean_send_notif(ccb_idx);
+ }
+ }
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_ignore_obx
+**
+** Description Ignore OBX event.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_ignore_obx(UINT8 ccb_idx, tBTA_MSE_DATA *p_data)
+{
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_ignore_obx ccb idx=%d ",ccb_idx);
+#endif
+
+ utl_freebuf((void **) &p_data->obx_evt.p_pkt);
+}
+
+
+
+/*****************************************************************************
+** MNC Callback Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_obx_cback
+**
+** Description OBX callback function.
+**
+** Parameters handle - Handle for Obex session
+** obx_event - Obex event
+** rsp_code - Obex response code
+** param - event parameters
+** p_pkt - pointer to Obex packet
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event, UINT8 rsp_code,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_MSE_OBX_EVT *p_obx_msg;
+ UINT16 event = 0;
+
+
+
+ switch (obx_event)
+ {
+ case OBX_CONNECT_RSP_EVT:
+ if (rsp_code == OBX_RSP_OK)
+ {
+ event = BTA_MSE_MN_OBX_CONN_RSP_EVT;
+ }
+ else /* Obex will disconnect underneath BTA */
+ {
+ APPL_TRACE_WARNING1("MN_OBX_CBACK: Bad connect response 0x%02x", rsp_code);
+ if (p_pkt)
+ GKI_freebuf(p_pkt);
+ return;
+ }
+ break;
+ case OBX_PUT_RSP_EVT:
+ event = BTA_MSE_MN_OBX_PUT_RSP_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_MSE_MN_OBX_CLOSE_EVT;
+ break;
+ case OBX_TIMEOUT_EVT:
+ event = BTA_MSE_MN_OBX_TOUT_EVT;
+ break;
+ case OBX_ABORT_RSP_EVT:
+ event = BTA_MSE_MN_OBX_ABORT_RSP_EVT;
+ break;
+ case OBX_PASSWORD_EVT:
+ case OBX_GET_RSP_EVT:
+ case OBX_SETPATH_RSP_EVT:
+ default:
+ /* case OBX_DISCONNECT_RSP_EVT: Handled when OBX_CLOSE_IND_EVT arrives */
+ if (p_pkt)
+ GKI_freebuf(p_pkt);
+ return;
+ }
+
+
+
+ if (event && (p_obx_msg =
+ (tBTA_MSE_OBX_EVT *) GKI_getbuf(sizeof(tBTA_MSE_OBX_EVT))) != NULL)
+ {
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ APPL_TRACE_DEBUG1("MN OBX Event Callback: mn_obx_event [%s]",
+ bta_mse_obx_evt_code(event));
+#endif
+ /* send event to BTA, if any */
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->hdr.layer_specific = 0xFFFF; /* not used */
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->rsp_code = rsp_code;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+
+
+/*****************************************************************************
+** Local MSE Event Processing Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_mse_req_app_access
+**
+** Description Sends an access request event to the application.
+**
+** Parameters ccb_idx - Index to the MN control block
+** p_data - Pointer to the MN event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_req_app_access (UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_ACCESS *p_acc_evt;
+ char *p_devname;
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_req_app_access inst idx=%d sess idx=%d",
+ inst_idx, sess_idx);
+#endif
+
+ /* Ask application for the operation's access permission */
+ if ((p_acc_evt = (tBTA_MSE_ACCESS *)GKI_getbuf((UINT16) (sizeof(tBTA_MSE_ACCESS)+
+ (p_bta_fs_cfg->max_path_len + 1)))) != NULL)
+ {
+ memset(p_acc_evt, 0, sizeof(tBTA_MSE_ACCESS));
+ p_acc_evt->p_path = (char *) (p_acc_evt+1);
+ p_acc_evt->p_path[0]='\0';
+
+ APPL_TRACE_API1("MSE ACCESS REQ: Oper=%d", p_cb->oper);
+ switch (p_cb->oper)
+ {
+ case BTA_MSE_OPER_SETPATH:
+ BCM_STRNCPY_S(p_acc_evt->p_path, p_bta_fs_cfg->max_path_len+1,
+ p_cb->sp.p_path, p_bta_fs_cfg->max_path_len);
+ break;
+
+ case BTA_MSE_OPER_GET_MSG_LIST:
+ BCM_STRNCPY_S(p_acc_evt->p_path, p_bta_fs_cfg->max_path_len+1,
+ p_cb->ml_param.p_path, p_bta_fs_cfg->max_path_len);
+ break;
+
+ case BTA_MSE_OPER_GET_MSG:
+ memcpy(p_acc_evt->handle, p_cb->msg_param.data.handle,
+ sizeof(tBTA_MA_MSG_HANDLE));
+ break;
+ case BTA_MSE_OPER_PUSH_MSG:
+ memset(p_acc_evt->handle, 0, sizeof(tBTA_MA_MSG_HANDLE));
+ BCM_STRNCPY_S(p_acc_evt->p_path, p_bta_fs_cfg->max_path_len+1,
+ p_cb->push_msg.param.p_folder, p_bta_fs_cfg->max_path_len);
+ break;
+ case BTA_MSE_OPER_DEL_MSG:
+ memcpy(p_acc_evt->handle, p_cb->set_msg_sts.handle,
+ sizeof(tBTA_MA_MSG_HANDLE));
+ p_acc_evt->delete_sts = p_cb->set_msg_sts.sts_val;
+ break;
+ default:
+ break;
+ }
+
+ p_acc_evt->oper = p_cb->oper;
+ p_acc_evt->mas_session_id = (tBTA_MA_SESS_HANDLE) p_cb->obx_handle;
+ bdcpy(p_acc_evt->bd_addr, p_cb->bd_addr);
+ if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL)
+ BCM_STRNCPY_S((char *)p_acc_evt->dev_name, sizeof(p_acc_evt->dev_name), p_devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ bta_mse_cb.p_cback(BTA_MSE_ACCESS_EVT, (tBTA_MSE *)p_acc_evt);
+ GKI_freebuf(p_acc_evt);
+ }
+}
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+
+/*******************************************************************************
+**
+** Function bta_mse_obx_evt_code
+**
+** Description get the obx event string pointer
+**
+** Parameters evt_code - obex event code
+**
+** Returns char * - event string pointer
+**
+*******************************************************************************/
+static char *bta_mse_obx_evt_code(UINT16 evt_code)
+{
+ switch (evt_code)
+ {
+ case BTA_MSE_MA_OBX_CONN_EVT:
+ return "BTA_MSE_MA_OBX_CONN_EVT";
+ case BTA_MSE_MA_OBX_DISC_EVT:
+ return "BTA_MSE_MA_OBX_DISC_EVT";
+ case BTA_MSE_MA_OBX_PUT_EVT:
+ return "BTA_MSE_MA_OBX_PUT_EVT";
+ case BTA_MSE_MA_OBX_GET_EVT:
+ return "BTA_MSE_MA_OBX_GET_EVT";
+ case BTA_MSE_MA_OBX_SETPATH_EVT:
+ return "BTA_MSE_MA_OBX_SETPATH_EVT";
+ case BTA_MSE_MA_OBX_ABORT_EVT:
+ return "BTA_MSE_MA_OBX_ABORT_EVT";
+ case BTA_MSE_MA_OBX_CLOSE_EVT:
+ return "BTA_MSE_MA_OBX_CLOSE_EVT";
+ case BTA_MSE_MN_OBX_TOUT_EVT:
+ return "BTA_MSE_MN_OBX_TOUT_EVT";
+ case BTA_MSE_MN_OBX_CONN_RSP_EVT:
+ return "BTA_MSE_MN_OBX_CONN_RSP_EVT";
+ case BTA_MSE_MN_OBX_PUT_RSP_EVT:
+ return "BTA_MSE_MN_OBX_PUT_RSP_EVT";
+ case BTA_MSE_MN_OBX_CLOSE_EVT:
+ return "BTA_MSE_MN_OBX_CLOSE_EVT";
+ case BTA_MSE_MN_OBX_ABORT_RSP_EVT:
+ return"BTA_MSE_MN_OBX_ABORT_RSP_EVT";
+ default:
+ return "unknown MSE OBX event code";
+ }
+}
+#endif /* Debug Functions */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif /* BTA_MSE_INCLUDED */
diff --git a/bta/ma/bta_mse_api.c b/bta/ma/bta_mse_api.c
new file mode 100644
index 0000000..5a2fd29
--- /dev/null
+++ b/bta/ma/bta_mse_api.c
@@ -0,0 +1,437 @@
+/*****************************************************************************
+**
+** Name: bta_mse_api.c
+**
+** Description: This is the implementation of the API for the Message
+** Acess Server subsystem of BTA, Broadcom Corp's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2009-2011 Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bd.h"
+#include "bta_ma_def.h"
+#include "bta_mse_api.h"
+#include "bta_fs_api.h"
+#include "bta_mse_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+static const tBTA_SYS_REG bta_mse_reg =
+{
+ bta_mse_hdl_event,
+ BTA_MseDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_MseEnable
+**
+** Description Enable the MSE subsystems. This function must be
+** called before any other functions in the MSE API are called.
+** When the enable operation is completed the callback function
+** will be called with an BTA_MSE_ENABLE_EVT event.
+**
+** Parameters p_cback - MSE event call back function
+** app_id - Application ID
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseEnable(tBTA_MSE_CBACK *p_cback, UINT8 app_id)
+{
+ tBTA_MSE_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_MSE, &bta_mse_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_MSE_API_ENABLE *)GKI_getbuf(sizeof(tBTA_MSE_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->app_id = app_id;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MseDisable
+**
+** Description Disable the MSE subsystem.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_MSE);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_MSE_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MseStart
+**
+** Description Start a MA server on the MSE
+**
+**
+** Parameters mas_inst_id - MAS instance ID
+** sec_mask - Security Setting Mask
+** MSE always enables
+** (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
+** p_service_name - Pointer to service name
+** p_root_path - Pointer to root path
+** (one level above telecom)
+** sup_msg_type - supported message type(s)
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseStart( tBTA_MA_INST_ID mas_inst_id,
+ tBTA_SEC sec_mask, const char *p_service_name,
+ const char *p_root_path,
+ tBTA_MA_MSG_TYPE sup_msg_type)
+{
+ tBTA_MSE_API_START *p_buf;
+
+ if ((p_buf = (tBTA_MSE_API_START *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_START) +
+ p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ p_buf->p_root_path = (char *)(p_buf + 1);
+ p_buf->hdr.event = BTA_MSE_API_START_EVT;
+ p_buf->mas_inst_id = mas_inst_id;
+ p_buf->sec_mask = (sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ p_buf->sup_msg_type = sup_msg_type;
+
+
+ if (p_service_name)
+ {
+ BCM_STRNCPY_S(p_buf->servicename, sizeof(p_buf->servicename), p_service_name, BTA_SERVICE_NAME_LEN);
+ p_buf->servicename[BTA_SERVICE_NAME_LEN] = '\0';
+ }
+ else
+ p_buf->servicename[0]= '\0';
+
+ if (p_root_path)
+ {
+ BCM_STRNCPY_S(p_buf->p_root_path, p_bta_fs_cfg->max_path_len+1, p_root_path, p_bta_fs_cfg->max_path_len);
+ p_buf->p_root_path[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ p_buf->p_root_path[0] = '\0';
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MseStop
+**
+** Description Stop a MA server on the MSE
+**
+** Parameters mas_instance_id - MAS Instance ID
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseStop (tBTA_MA_INST_ID mas_instance_id)
+{
+ tBTA_MSE_API_STOP *p_buf;
+
+ if ((p_buf = (tBTA_MSE_API_STOP *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_STOP)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_API_STOP_EVT;
+ p_buf->mas_inst_id = mas_instance_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MseClose
+**
+** Description Close all MAS sessions on the specified MAS Instance ID
+**
+** Parameters mas_instance_id - MAS Inatance ID
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseClose(tBTA_MA_INST_ID mas_instance_id)
+{
+
+ tBTA_MSE_API_CLOSE *p_buf;
+
+ if ((p_buf = (tBTA_MSE_API_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_CLOSE)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_API_CLOSE_EVT;
+ p_buf->mas_instance_id = mas_instance_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MseMaClose
+**
+** Description Close a MAS sessions on the specified BD address
+**
+** Parameters bd_addr - remote BD's address
+** mas_instance_id - MAS Inatance ID
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseMaClose(BD_ADDR bd_addr, tBTA_MA_INST_ID mas_instance_id)
+{
+ tBTA_MSE_API_MA_CLOSE *p_buf;
+
+ if ((p_buf = (tBTA_MSE_API_MA_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_MA_CLOSE)))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_MSE_API_MA_CLOSE));
+
+ p_buf->hdr.event = BTA_MSE_API_MA_CLOSE_EVT;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ p_buf->mas_instance_id = mas_instance_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_MseMnClose
+**
+** Description Close a MN session
+**
+** Parameters bd_addr - remote BD's address
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseMnClose(BD_ADDR bd_addr)
+{
+ tBTA_MSE_API_MN_CLOSE *p_buf;
+
+ if ((p_buf = (tBTA_MSE_API_MN_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_MN_CLOSE)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_API_MN_CLOSE_EVT;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MseAccessRsp
+**
+** Description Send a response for the access request
+**
+** Parameters mas_session_id - MAS session ID
+** oper - MAS operation type
+** access - Access is allowed or not
+** p_path - pointer to a path if if the operation
+** involves accessing a folder
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseAccessRsp(tBTA_MA_SESS_HANDLE mas_session_id, tBTA_MSE_OPER oper,
+ tBTA_MA_ACCESS_TYPE access, char *p_path)
+{
+ tBTA_MSE_API_ACCESSRSP *p_acc_rsp;
+ UINT16 path_len;
+
+ /* If directory is specified set the length */
+ path_len = (p_path && *p_path != '\0') ? (UINT16)(strlen(p_path) + 1): 1;
+
+ if ((p_acc_rsp = (tBTA_MSE_API_ACCESSRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_ACCESSRSP)
+ + path_len))) != NULL)
+ {
+ p_acc_rsp->mas_session_id = mas_session_id;
+ p_acc_rsp->rsp = access;
+ p_acc_rsp->oper = oper;
+ p_acc_rsp->p_path = (char *)(p_acc_rsp + 1);
+ if (p_path)
+ {
+ BCM_STRNCPY_S(p_acc_rsp->p_path, path_len, p_path, path_len-1);
+ p_acc_rsp->p_path[path_len-1] = '\0';
+ }
+ else
+ p_acc_rsp->p_path[0] = '\0';
+
+ p_acc_rsp->hdr.event = BTA_MSE_API_ACCESSRSP_EVT;
+ bta_sys_sendmsg(p_acc_rsp);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_MseUpdateInboxRsp
+**
+** Description Send a response for the update inbox request
+**
+**
+** Parameters mas_session_id - MAS session ID
+** update_rsp - update inbox is allowed or not
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseUpdateInboxRsp(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MSE_UPDATE_INBOX_TYPE update_rsp)
+{
+ tBTA_MSE_API_UPDINBRSP *p_buf;
+
+ if ((p_buf = (tBTA_MSE_API_UPDINBRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_UPDINBRSP)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_API_UPD_IBX_RSP_EVT;
+ p_buf->mas_session_id = mas_session_id;
+ p_buf->rsp = update_rsp;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_MseSetNotifRegRsp
+**
+** Description Send a response for the set notification registration
+**
+**
+** Parameters mas_session_id - MAS session ID
+** set_notif_reg_rsp - indicate whether the set notification
+** registration is allowed or not
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseSetNotifRegRsp(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MSE_SET_NOTIF_REG_TYPE set_notif_reg_rsp)
+{
+ tBTA_MSE_API_SETNOTIFREGRSP *p_buf;
+
+ if ((p_buf = (tBTA_MSE_API_SETNOTIFREGRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_API_UPDINBRSP)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_API_SET_NOTIF_REG_RSP_EVT;
+ p_buf->mas_session_id = mas_session_id;
+ p_buf->rsp = set_notif_reg_rsp;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_MseSendNotif
+**
+** Description Send a Message notification report to all MCEs registered with
+** the specified MAS instance ID
+**
+** Parameters mas_instance_id - MAS Instance ID
+** notif_type - message notification type
+** handle - message handle
+** p_folder - pointer to current folder
+** p_old_folder - pointer to older folder
+** msg_type - message type (E_MAIL, SMS_GSM, SMS_CDMA, MMS)
+** except_bd_addr - except to the MCE on this BD Address.
+** (Note: notification will be not sent to
+** this BD Addreess)
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseSendNotif(tBTA_MA_INST_ID mas_instance_id,
+ tBTA_MSE_NOTIF_TYPE notif_type,
+ tBTA_MA_MSG_HANDLE handle,
+ char * p_folder, char *p_old_folder,
+ tBTA_MA_MSG_TYPE msg_type,
+ BD_ADDR except_bd_addr)
+{
+ tBTA_MSE_MN_API_SEND_NOTIF *p_buf;
+ UINT16 folder_len, old_folder_len;
+
+ /* If directory is specified set the length */
+ folder_len = (p_folder && *p_folder != '\0') ? (UINT16)(strlen(p_folder) + 1): 0;
+ old_folder_len = (p_old_folder && *p_old_folder != '\0') ? (UINT16)(strlen(p_old_folder) + 1): 0;
+
+ if ((p_buf = (tBTA_MSE_MN_API_SEND_NOTIF *)GKI_getbuf((UINT16) ((UINT16)sizeof(tBTA_MSE_MN_API_SEND_NOTIF) +
+ folder_len +
+ old_folder_len))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_API_SEND_NOTIF_EVT;
+ p_buf->mas_instance_id = mas_instance_id;
+ p_buf->notif_type = notif_type;
+ memcpy(p_buf->handle, handle, sizeof(tBTA_MA_MSG_HANDLE));
+
+ if (folder_len)
+ {
+ p_buf->p_folder = (char *)(p_buf + 1);
+ BCM_STRNCPY_S(p_buf->p_folder, folder_len+1, p_folder, folder_len);
+ }
+ else
+ p_buf->p_folder = NULL;
+
+ if (old_folder_len)
+ {
+ if (folder_len)
+ p_buf->p_old_folder = p_buf->p_folder + folder_len;
+ else
+ p_buf->p_old_folder = (char *)(p_buf + 1);
+
+ BCM_STRNCPY_S(p_buf->p_old_folder, old_folder_len+1, p_old_folder, old_folder_len);
+ }
+ else
+ p_buf->p_old_folder = NULL;
+
+ p_buf->msg_type = msg_type;
+ if (except_bd_addr != NULL)
+ {
+ bdcpy(p_buf->except_bd_addr, except_bd_addr);
+ }
+ else
+ {
+ memset(p_buf->except_bd_addr, 0, sizeof(BD_ADDR));
+ }
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_MseMnAbort
+**
+** Description Abort the current OBEX multi-packt operation in MN
+**
+** Parameters mas_instance_id - MAS Instance ID
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_MseMnAbort(tBTA_MA_INST_ID mas_instance_id)
+{
+ tBTA_MSE_MN_API_ABORT *p_buf;
+
+ if ((p_buf = (tBTA_MSE_MN_API_ABORT *)GKI_getbuf((UINT16)(sizeof(tBTA_MSE_MN_API_ABORT)))) != NULL)
+ {
+ p_buf->hdr.event = BTA_MSE_API_MN_ABORT_EVT;
+ p_buf->mas_instance_id = mas_instance_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
+#endif /* BTA_MSE_INCLUDED */
diff --git a/bta/ma/bta_mse_cfg.c b/bta/ma/bta_mse_cfg.c
new file mode 100644
index 0000000..69953d0
--- /dev/null
+++ b/bta/ma/bta_mse_cfg.c
@@ -0,0 +1,31 @@
+/*****************************************************************************
+**
+** Name: bta_mse_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the MSE subsystem.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_mse_api.h"
+
+#ifndef BTA_MSE_MAX_NAME_LEN
+ #define BTA_MSE_MAX_NAME_LEN 256
+#endif
+
+#ifndef BTA_MSE_OBX_RSP_TOUT
+ #define BTA_MSE_OBX_RSP_TOUT 2000
+#endif
+
+
+const tBTA_MSE_CFG bta_mse_cfg =
+{
+ BTA_MSE_OBX_RSP_TOUT,
+ BTA_MSE_MAX_NAME_LEN
+};
+
+tBTA_MSE_CFG *p_bta_mse_cfg = (tBTA_MSE_CFG *)&bta_mse_cfg;
+
diff --git a/bta/ma/bta_mse_ci.c b/bta/ma/bta_mse_ci.c
new file mode 100644
index 0000000..dfaeb7e
--- /dev/null
+++ b/bta/ma/bta_mse_ci.c
@@ -0,0 +1,251 @@
+/*****************************************************************************
+**
+** Name: bta_mse_ci.c
+**
+** Description: This is the implementaion for the Message Server Equipment
+** (MSE) subsystem call-in functions.
+**
+** Copyright (c) 2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#include <stdio.h>
+#include <string.h>
+#include "bta_api.h"
+#include "bta_ma_def.h"
+#include "bta_mse_api.h"
+#include "bta_mse_co.h"
+#include "bta_mse_int.h"
+#include "bta_mse_ci.h"
+
+/*******************************************************************************
+**
+** Function bta_mse_ci_get_folder_entry
+**
+** Description This function is called in response to the
+** bta_mse_co_get_folder_entry call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK if p_entry points to a valid entry.
+** BTA_MA_STATUS_EODIR if no more entries (p_entry is ignored).
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_ci_get_folder_entry(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 evt)
+{
+ tBTA_MSE_CI_GET_FENTRY *p_evt;
+
+ if ((p_evt = (tBTA_MSE_CI_GET_FENTRY *)GKI_getbuf(sizeof(tBTA_MSE_CI_GET_FENTRY))) != NULL)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ci_get_folder_entry sess_id=%d, status=%d \n",
+ mas_session_id, status);
+#endif
+ p_evt->hdr.event = evt;
+ p_evt->mas_session_id = mas_session_id;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_mse_ci_get_msg_list_info
+**
+** Description This function is called in response to the
+** bta_mse_co_get_msg_list_info call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK 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_mse_ci_get_msg_list_info(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 evt)
+{
+ tBTA_MSE_CI_GET_ML_INFO *p_evt;
+
+ if ((p_evt = (tBTA_MSE_CI_GET_ML_INFO *)GKI_getbuf(sizeof(tBTA_MSE_CI_GET_ML_INFO))) != NULL)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ci_get_msg_list_info sess_id=%d, status=%d \n",
+ mas_session_id, status);
+#endif
+ p_evt->hdr.event = evt;
+ p_evt->mas_session_id = mas_session_id;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ci_get_msg_list_entry
+**
+** Description This function is called in response to the
+** bta_mse_co_get_msg_list_entry call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK if p_entry points to a valid entry.
+** BTA_MA_STATUS_EODIR if no more entries (p_entry is ignored).
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_ci_get_msg_list_entry(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 evt)
+{
+ tBTA_MSE_CI_GET_ML_ENTRY *p_evt;
+
+ if ((p_evt = (tBTA_MSE_CI_GET_ML_ENTRY *)GKI_getbuf(sizeof(tBTA_MSE_CI_GET_ML_ENTRY))) != NULL)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_ci_get_msg_list_entry sess_id=%d, status=%d \n",
+ mas_session_id, status);
+#endif
+ p_evt->hdr.event = evt;
+ p_evt->mas_session_id = mas_session_id;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ci_get_msg
+**
+** Description This function is called in response to the
+** bta_mse_co_get_msg call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK if p_msg points to a valid bmessage.
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** filled_buff_size - size of the filled buffer
+** multi_pkt_status - BTA_MA_MPKT_STATUS_MORE - need to get more packets
+** BTA_MA_MPKT_STATUS_LAST - last packet of the bMessage
+** frac_deliver_status - BTA_MA_FRAC_DELIVER_MORE - other fractions following
+** this bMessage
+** BTA_MA_FRAC_DELIVER_LAST - Last fraction
+** evt - evt from the call-out function
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_ci_get_msg(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 filled_buff_size,
+ tBTA_MA_MPKT_STATUS multi_pkt_status,
+ tBTA_MA_FRAC_DELIVER frac_deliver_status,
+ UINT16 evt)
+{
+ tBTA_MSE_CI_GET_MSG *p_evt;
+
+ if ((p_evt = (tBTA_MSE_CI_GET_MSG *)GKI_getbuf(sizeof(tBTA_MSE_CI_GET_MSG))) != NULL)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT4("bta_mse_ci_get_msg sess_id=%d, status=%d, multi-pkt status=%d frac=%d\n",
+ mas_session_id,
+ status,
+ multi_pkt_status,
+ frac_deliver_status);
+#endif
+ p_evt->hdr.event = evt;
+ p_evt->mas_session_id = mas_session_id;
+ p_evt->status = status;
+ p_evt->filled_buff_size = filled_buff_size;
+ p_evt->multi_pkt_status = multi_pkt_status;
+ p_evt->frac_deliver_status = frac_deliver_status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+/*******************************************************************************
+**
+** Function bta_mse_ci_set_msg_delete_status
+**
+** Description This function is called in response to the
+** bta_mse_co_set_msg_delete_status call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** 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_mse_ci_set_msg_delete_status(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ UINT16 evt)
+{
+ tBTA_MSE_CI_DEL_MSG *p_evt;
+
+ if ((p_evt = (tBTA_MSE_CI_DEL_MSG *)GKI_getbuf(sizeof(tBTA_MSE_CI_DEL_MSG))) != NULL)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("bta_mse_ci_del_msg sess_id=%d, status=%d evt=%d\n",
+ mas_session_id, status, evt);
+#endif
+ p_evt->hdr.event = evt;
+ p_evt->mas_session_id = mas_session_id;
+ p_evt->status = status;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ci_push_msg
+**
+** Description This function is called in response to the
+** bta_mse_co_push_msg call-out function.
+**
+** Parameters mas_session_id - MAS session ID
+** status - BTA_MA_STATUS_OK if the message upload is successful.
+** BTA_MA_STATUS_FAIL if any errors have occurred.
+** last_packet - last packet of a multi-packet message
+** handle - message handle for the uploaded message if
+** status is BTA_MA_OK and last_packet is TRUE
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_mse_ci_push_msg(tBTA_MA_SESS_HANDLE mas_session_id,
+ tBTA_MA_STATUS status,
+ BOOLEAN last_packet,
+ tBTA_MA_MSG_HANDLE handle,
+ UINT16 evt)
+{
+ tBTA_MSE_CI_PUSH_MSG *p_evt;
+
+ if ((p_evt = (tBTA_MSE_CI_PUSH_MSG *)GKI_getbuf(sizeof(tBTA_MSE_CI_PUSH_MSG))) != NULL)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT4("bta_mse_ci_push_msg sess_id=%d, status=%d, last_pkt=%d evt=%d\n",
+ mas_session_id,
+ status,
+ last_packet,
+ evt);
+#endif
+
+ p_evt->hdr.event = evt;
+ p_evt->mas_session_id = mas_session_id;
+ p_evt->status = status;
+ memcpy(p_evt->handle,
+ handle,
+ sizeof(tBTA_MA_MSG_HANDLE));
+ p_evt->last_packet = last_packet;
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+
diff --git a/bta/ma/bta_mse_int.h b/bta/ma/bta_mse_int.h
new file mode 100644
index 0000000..d519b71
--- /dev/null
+++ b/bta/ma/bta_mse_int.h
@@ -0,0 +1,835 @@
+/*****************************************************************************
+**
+** Name: bta_mse_int.h
+**
+** Description: This is the private file for the message access
+** equipment (MSE) subsystem.
+**
+** Copyright (c) 1998-2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_MSE_INT_H
+#define BTA_MSE_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_ma_def.h"
+#include "bta_mse_api.h"
+#include "bta_mse_co.h"
+#include "bta_mse_ci.h"
+#include "bta_ma_util.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+typedef tOBX_STATUS (tBTA_MA_OBX_RSP) (tOBX_HANDLE handle, UINT8 rsp_code, BT_HDR *p_pkt);
+
+#ifndef BTA_MSE_MN_DISC_SIZE
+ #define BTA_MSE_MN_DISC_SIZE 500
+#endif
+
+#define BTA_MSE_64BIT_HEX_STR_SIZE (16+1)
+#define BTA_MSE_32BIT_HEX_STR_SIZE (8+1)
+
+#define BTA_MSE_MN_MAX_MSG_EVT_OBECT_SIZE 1536 /* 1.5 k */
+/* mode field in tBTA_MSE_CO_FOLDER_ENTRY (OR'd together) */
+#define BTA_MSE_A_RDONLY GOEP_A_RDONLY
+#define BTA_MSE_A_DIR GOEP_A_DIR /* Entry is a sub directory */
+
+enum
+{
+ BTA_MSE_MA_GET_ACT_NEW_FOLDER_LIST = 0,
+ BTA_MSE_MA_GET_ACT_CON_FOLDER_LIST,
+ BTA_MSE_MA_GET_ACT_ERR_FOLDER_LIST,
+ BTA_MSE_MA_GET_ACT_NEW_MSG_LIST,
+ BTA_MSE_MA_GET_ACT_CON_MSG_LIST,
+ BTA_MSE_MA_GET_ACT_ERR_MSG_LIST,
+ BTA_MSE_MA_GET_ACT_NEW_MSG,
+ BTA_MSE_MA_GET_ACT_CON_MSG,
+ BTA_MSE_MA_GET_ACT_ERR_MSG,
+ BTA_MSE_MA_GET_ACT_ERR,
+ BTA_MSE_MA_GET_ACT_NONE,
+ BTA_MSE_MA_GET_ACT_MAX
+};
+typedef UINT8 tBTA_MSE_MA_GET_ACT;
+
+enum
+{
+ BTA_MSE_MA_GET_TYPE_FOLDER_LIST = 0,
+ BTA_MSE_MA_GET_TYPE_MSG_LIST,
+ BTA_MSE_MA_GET_TYPE_MSG,
+ BTA_MSE_MA_GET_TYPE_CON_FOLDER_LIST,
+ BTA_MSE_MA_GET_TYPE_CON_MSG_LIST,
+ BTA_MSE_MA_GET_TYPE_CON_MSG,
+ BTA_MSE_MA_GET_TYPE_NONE,
+ BTA_MSE_MA_GET_TYPE_MAX
+};
+typedef UINT8 tBTA_MSE_MA_GET_TYPE;
+
+enum
+{
+ BTA_MSE_MA_PUT_TYPE_NOTIF_REG = 0,
+ BTA_MSE_MA_PUT_TYPE_EVT_RPT,
+ BTA_MSE_MA_PUT_TYPE_NONE,
+ BTA_MSE_MA_PUT_TYPE_MAX
+};
+typedef UINT8 tBTA_MSE_MA_PUT_TYPE;
+
+enum
+{
+ BTA_MSE_MN_NOTIF_REG_STS_OFF = 0,
+ BTA_MSE_MN_NOTIF_REG_STS_ON,
+ BTA_MSE_MN_NOTIF_REG_STS_NONE,
+ BTA_MSE_MN_NOTIF_REG_STS_MAX
+};
+typedef UINT8 tBTA_MSE_MN_NOTIF_REG_STS;
+
+enum
+{
+ BTA_MSE_MN_ACT_TYPE_OPEN_CONN = 0,
+ BTA_MSE_MN_ACT_TYPE_OPEN_CONN_NONE,
+ BTA_MSE_MN_ACT_TYPE_OPEN_CONN_ERR,
+ BTA_MSE_MN_ACT_TYPE_CLOSE_CONN,
+ BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_NONE,
+ BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_ERR,
+ BTA_MSE_MN_ACT_TYPE_NONE,
+ BTA_MSE_MN_ACT_TYPE_MAX
+};
+typedef UINT8 tBTA_MSE_MN_ACT_TYPE;
+
+typedef tOBX_STATUS (tBTA_MSE_OBX_RSP) (tOBX_HANDLE handle, UINT8 rsp_code, BT_HDR *p_pkt);
+
+/* MSE Active MA obex operation (Valid in connected state) */
+#define BTA_MSE_MA_OP_NONE 0
+#define BTA_MSE_MA_OP_SETPATH 1
+#define BTA_MSE_MA_OP_GET_FOLDER_LIST 2
+#define BTA_MSE_MA_OP_GET_MSG_LIST 3
+#define BTA_MSE_MA_OP_GET_MSG 4
+#define BTA_MSE_MA_OP_SET_STATUS 5
+#define BTA_MSE_MA_OP_PUSH_MSG 6
+
+/* MAS Active MN obex operation (Valid in connected state) */
+#define BTA_MSE_MN_OP_NONE 0
+#define BTA_MSE_MN_OP_PUT_EVT_RPT 1
+
+
+/* MN Abort state */
+#define BTA_MSE_MN_ABORT_NONE 0x0
+#define BTA_MSE_MN_ABORT_REQ_NOT_SENT 0x1
+#define BTA_MSE_MN_ABORT_REQ_SENT 0x2
+#define BTA_MSE_MN_ABORT_RSP_RCVD 0x4
+
+
+/* Response Timer Operations */
+#define BTA_MSE_TIMER_OP_NONE 0
+#define BTA_MSE_TIMER_OP_STOP 1
+#define BTA_MSE_TIMER_OP_ABORT 2
+#define BTA_MSE_TIMER_OP_ALL 0xFF /* use to stop all timers */
+
+/* State Machine Events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_MSE_INT_CLOSE_EVT = BTA_SYS_EVT_START(BTA_ID_MSE),
+ BTA_MSE_API_ACCESSRSP_EVT,
+ BTA_MSE_API_UPD_IBX_RSP_EVT,
+ BTA_MSE_API_SET_NOTIF_REG_RSP_EVT,
+ BTA_MSE_INT_START_EVT,
+ BTA_MSE_CI_GET_FENTRY_EVT,
+ BTA_MSE_CI_GET_ML_INFO_EVT,
+ BTA_MSE_CI_GET_ML_ENTRY_EVT,
+ BTA_MSE_CI_GET_MSG_EVT,
+ BTA_MSE_CI_PUSH_MSG_EVT,
+ BTA_MSE_CI_DEL_MSG_EVT,
+ BTA_MSE_MA_OBX_CONN_EVT, /* OBX Channel Connect Request */
+ BTA_MSE_MA_OBX_DISC_EVT, /* OBX Channel Disconnect */
+ BTA_MSE_MA_OBX_ABORT_EVT, /* OBX_operation aborted */
+ BTA_MSE_MA_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_MSE_MA_OBX_PUT_EVT, /* Write file data or delete */
+ BTA_MSE_MA_OBX_GET_EVT, /* Read file data or folder listing */
+ BTA_MSE_MA_OBX_SETPATH_EVT, /* Make or Change Directory */
+ BTA_MSE_CLOSE_CMPL_EVT, /* Finished closing channel */
+
+ /* Message Notification Client events */
+ BTA_MSE_MN_INT_OPEN_EVT,
+ BTA_MSE_MN_INT_CLOSE_EVT,
+ BTA_MSE_MN_SDP_OK_EVT,
+ BTA_MSE_MN_SDP_FAIL_EVT,
+ BTA_MSE_MN_OBX_CONN_RSP_EVT,
+ BTA_MSE_MN_OBX_PUT_RSP_EVT,
+ BTA_MSE_MN_OBX_CLOSE_EVT,
+ BTA_MSE_MN_OBX_TOUT_EVT,
+ BTA_MSE_MN_CLOSE_CMPL_EVT,
+ BTA_MSE_API_SEND_NOTIF_EVT,
+ BTA_MSE_API_MN_ABORT_EVT,
+ BTA_MSE_MN_OBX_ABORT_RSP_EVT,
+ BTA_MSE_MN_RSP_TOUT_EVT,
+
+ /* these events are handled outside the state machine */
+ BTA_MSE_MN_RSP0_TOUT_EVT, /* timeout event for MN control block index 0*/
+ BTA_MSE_MN_RSP1_TOUT_EVT,
+ BTA_MSE_MN_RSP2_TOUT_EVT,
+ BTA_MSE_MN_RSP3_TOUT_EVT,
+ BTA_MSE_MN_RSP4_TOUT_EVT,
+ BTA_MSE_MN_RSP5_TOUT_EVT,
+ BTA_MSE_MN_RSP6_TOUT_EVT, /* Bluetooth limit for upto 7 devices*/
+ BTA_MSE_API_ENABLE_EVT,
+ BTA_MSE_API_DISABLE_EVT,
+ BTA_MSE_API_START_EVT,
+ BTA_MSE_API_STOP_EVT,
+ BTA_MSE_API_CLOSE_EVT,
+ BTA_MSE_API_MA_CLOSE_EVT,
+ BTA_MSE_API_MN_CLOSE_EVT
+
+};
+typedef UINT16 tBTA_MSE_INT_EVT;
+
+#define BTA_MSE_MN_EVT_MIN BTA_MSE_MN_INT_OPEN_EVT
+#define BTA_MSE_MN_EVT_MAX BTA_MSE_MN_RSP_TOUT_EVT
+
+
+/* state machine states */
+enum
+{
+ BTA_MSE_MA_IDLE_ST = 0, /* Idle */
+ BTA_MSE_MA_LISTEN_ST, /* Listen - waiting for OBX/RFC connection */
+ BTA_MSE_MA_CONN_ST, /* Connected - MA Session is active */
+ BTA_MSE_MA_CLOSING_ST /* Closing is in progress */
+};
+typedef UINT8 tBTA_MSE_MA_STATE;
+
+/* data type for BTA_MSE_MA_CI_GET_FENTRY_EVT note:sdh */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_STATUS status;
+} tBTA_MSE_CI_GET_FENTRY;
+
+/* data type for BTA_MSE_MA_CI_GET_FENTRY_EVT note:sdh */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_STATUS status;
+} tBTA_MSE_CI_GET_ML_INFO;
+
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_STATUS status;
+} tBTA_MSE_CI_GET_ML_ENTRY;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_STATUS status;
+ BOOLEAN last_packet;
+ tBTA_MA_MSG_HANDLE handle;
+} tBTA_MSE_CI_PUSH_MSG;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_STATUS status;
+ UINT16 filled_buff_size;
+ tBTA_MA_MPKT_STATUS multi_pkt_status;
+ tBTA_MA_FRAC_DELIVER frac_deliver_status;
+} tBTA_MSE_CI_GET_MSG;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MA_STATUS status;
+} tBTA_MSE_CI_DEL_MSG;
+
+
+
+/* data type for BTA_MSE_API_ENABLE_EVT note:sdh */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MSE_CBACK *p_cback; /* pointer to application callback function */
+ UINT8 app_id;
+} tBTA_MSE_API_ENABLE;
+
+
+/* data type for BTA_MSE_API_DISABLE_EVT note:sdh */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 app_id;
+} tBTA_MSE_API_DISABLE;
+
+/* data type for BTA_MSE_API_START_EVT note:sdh */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_INST_ID mas_inst_id;
+ char servicename[BTA_SERVICE_NAME_LEN + 1];
+ char *p_root_path;
+ tBTA_SEC sec_mask;
+ tBTA_MA_MSG_TYPE sup_msg_type;
+} tBTA_MSE_API_START;
+
+/* data type for BTA_MSE_API_STOP_EVT note:sdh */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_INST_ID mas_inst_id;
+
+} tBTA_MSE_API_STOP;
+
+/* data type for BTA_MSE_API_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_INST_ID mas_instance_id;
+
+} tBTA_MSE_API_CLOSE;
+
+/* data type for BTA_MSE_API_MA_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ tBTA_MA_INST_ID mas_instance_id;
+
+} tBTA_MSE_API_MA_CLOSE;
+
+/* data type for BTA_MSE_INT_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+
+} tBTA_MSE_INT_CLOSE;
+
+
+/* data type for BTA_MSE_API_MN_CLOSE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+} tBTA_MSE_API_MN_CLOSE;
+
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MSE_OPER oper;
+ tBTA_MA_ACCESS_TYPE rsp;
+ char *p_path;
+} tBTA_MSE_API_ACCESSRSP;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MSE_UPDATE_INBOX_TYPE rsp;
+ char *p_path;
+} tBTA_MSE_API_UPDINBRSP;
+
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_SESS_HANDLE mas_session_id;
+ tBTA_MSE_SET_NOTIF_REG_TYPE rsp;
+} tBTA_MSE_API_SETNOTIFREGRSP;
+
+/* data type for all obex events
+ hdr.event contains the MAS event
+*/
+typedef struct
+{
+ BT_HDR hdr;
+ tOBX_HANDLE handle;
+ tOBX_EVT_PARAM param;
+ BT_HDR *p_pkt;
+ tOBX_EVENT obx_event;
+ UINT8 rsp_code;
+} tBTA_MSE_OBX_EVT;
+
+/* OBX Response Packet Structure - Holds current response packet info */
+typedef struct
+{
+ BT_HDR *p_pkt; /* (Get/Put) Holds the current OBX header for Put or Get */
+ UINT8 *p_start; /* (Get/Put) Start of the Body of the packet */
+ UINT16 offset; /* (Get/Put) Contains the current offset into the Body (p_start) */
+ UINT16 bytes_left; /* (Get/Put) Holds bytes available left in Obx packet */
+ BOOLEAN final_pkt; /* (Put) Holds the final bit of the Put packet */
+} tBTA_MSE_OBX_PKT;
+
+/* data type for BTA_MSE_MN_INT_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 ccb_idx;
+ BD_ADDR bd_addr;
+ tBTA_SEC sec_mask;
+}tBTA_MSE_MN_INT_OPEN;
+
+/* data type for BTA_MSE_MN_INT_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 ccb_idx;
+}tBTA_MSE_MN_INT_CLOSE;
+
+/* data type for BTA_MSE_MN_SDP_OK_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 ccb_idx;
+ UINT8 scn;
+}tBTA_MSE_MN_SDP_OK;
+
+
+/* data type for BTA_MSE_MN_SDP_FAIL_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 ccb_idx;
+}tBTA_MSE_MN_SDP_FAIL;
+
+
+/* data type for BTA_MSE_MN_API_SEND_NOTIF_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_INST_ID mas_instance_id;
+ tBTA_MSE_NOTIF_TYPE notif_type;
+ tBTA_MA_MSG_HANDLE handle;
+ char *p_folder;
+ char *p_old_folder;
+ tBTA_MA_MSG_TYPE msg_type;
+ BD_ADDR except_bd_addr;
+} tBTA_MSE_MN_API_SEND_NOTIF;
+
+/* data type for BTA_MSE_API_MN_ABORT_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_MA_INST_ID mas_instance_id;
+}tBTA_MSE_MN_API_ABORT;
+
+
+/* union of all state machine event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_MSE_API_ENABLE api_enable; /* data for BTA_MSE_API_ENABLE_EVT */
+ tBTA_MSE_API_DISABLE api_disable;
+ tBTA_MSE_API_START api_start;
+ tBTA_MSE_API_STOP api_stop;
+ tBTA_MSE_API_CLOSE api_close;
+ tBTA_MSE_INT_CLOSE int_close;
+ tBTA_MSE_API_MA_CLOSE api_ma_close;
+ tBTA_MSE_API_MN_CLOSE api_mn_close;
+ tBTA_MSE_API_ACCESSRSP api_access_rsp;
+ tBTA_MSE_API_UPDINBRSP api_upd_ibx_rsp;
+ tBTA_MSE_API_SETNOTIFREGRSP api_set_notif_reg_rsp;
+ tBTA_MSE_OBX_EVT obx_evt;
+ tBTA_MSE_CI_GET_FENTRY ci_get_fentry;
+ tBTA_MSE_CI_GET_ML_INFO ci_get_ml_info;
+ tBTA_MSE_CI_GET_ML_ENTRY ci_get_ml_entry;
+ tBTA_MSE_CI_GET_MSG ci_get_msg;
+ tBTA_MSE_CI_PUSH_MSG ci_push_msg;
+ tBTA_MSE_CI_DEL_MSG ci_del_msg;
+ tBTA_MSE_MN_INT_OPEN mn_int_open;
+ tBTA_MSE_MN_INT_CLOSE mn_int_close;
+ tBTA_MSE_MN_SDP_OK mn_sdp_ok;
+ tBTA_MSE_MN_SDP_FAIL mn_sdp_fail;
+ tBTA_MSE_MN_API_SEND_NOTIF mn_send_notif;
+ tBTA_MSE_MN_API_ABORT mn_abort;
+
+} tBTA_MSE_DATA;
+
+typedef struct
+{
+ char *p_path;
+ char *p_name;
+ tBTA_MA_DIR_NAV flags;
+} tBTA_MSE_OPER_SETPATH;
+
+/* Directory Listing bufer pointer */
+typedef struct
+{
+ tBTA_MSE_CO_FOLDER_ENTRY *p_entry; /* Holds current directory entry */
+ BOOLEAN is_root; /* TRUE if path is root directory */
+} tBTA_MSE_DIRLIST;
+
+typedef struct
+{
+ UINT16 max_list_cnt;
+ UINT16 start_offset;
+ UINT16 list_cnt;
+} tBTA_MSE_OPER_FLIST_PARAM;
+
+/* Message Listing buffer pointers */
+typedef struct
+{
+ tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry;
+ tBTA_MSE_CO_MSG_LIST_INFO *p_info;
+ BOOLEAN pending_ml_frag;
+ char *p_xml_buf;
+ UINT16 offset;
+ UINT16 remaing_size;
+} tBTA_MSE_MSGLIST;
+
+typedef struct
+{
+ tBTA_MA_MSG_LIST_FILTER_PARAM filter;
+ char *p_name;
+ char *p_path;
+ BOOLEAN w4info;
+} tBTA_MSE_OPER_MLIST_PARAM;
+
+
+typedef struct
+{
+ BOOLEAN notif_status_rcv;
+ tBTA_MA_NOTIF_STATUS notif_status;
+} tBTA_NOTIF_REG;
+
+typedef struct
+{
+ tBTA_MA_GET_MSG_PARAM data;
+ char *p_msg_handle;
+ UINT8 *p_frac_delivery;
+ UINT16 byte_get_cnt;
+ UINT16 filled_buff_size;
+ BOOLEAN add_frac_del_hdr;
+ tBTA_MA_FRAC_DELIVER frac_deliver_status;
+} tBTA_MSE_OPER_MSG_PARAM;
+
+typedef struct
+{
+ tBTA_MA_PUSH_MSG_PARAM param;
+ UINT16 push_byte_cnt;
+ BOOLEAN rcv_folder_name;
+ BOOLEAN rcv_charset;
+ BOOLEAN rcv_transparent;
+ BOOLEAN rcv_retry;
+ BOOLEAN first_req_pkt;
+} tBTA_MSE_OPER_PUSH_MSG;
+
+typedef struct
+{
+ char *p_msg_handle;
+ BOOLEAN rcv_msg_handle;
+ BOOLEAN rcv_sts_ind;
+ BOOLEAN rcv_sts_val;
+ tBTA_MA_MSG_HANDLE handle;
+ tBTA_MA_STS_INDCTR sts_ind;
+ tBTA_MA_STS_VALUE sts_val;
+} tBTA_MSE_OPER_SET_MSG_STS;
+
+
+/* MAS control block */
+typedef struct
+{
+ tBTA_NOTIF_REG notif_reg_req;
+ tBTA_MSE_OPER_PUSH_MSG push_msg;
+ tBTA_MSE_OPER_SET_MSG_STS set_msg_sts;
+ tBTA_MSE_OPER_SETPATH sp;
+ tBTA_MSE_OPER_FLIST_PARAM fl_param;
+ tBTA_MSE_DIRLIST dir;
+ tBTA_MSE_OPER_MLIST_PARAM ml_param;
+ tBTA_MSE_MSGLIST ml; /* point to the Message-Listing object buffer */
+ tBTA_MSE_OPER_MSG_PARAM msg_param;
+ tBTA_MSE_OBX_PKT obx;
+ char *p_workdir; /* Current working folder */
+ tOBX_HANDLE obx_handle; /* OBEX handle,used as MAS session ID as well */
+ UINT16 peer_mtu;
+ BOOLEAN cout_active; /* TRUE when waiting for a call-in function */
+ BOOLEAN aborting;
+ BD_ADDR bd_addr; /* Device currently connected to */
+ tBTA_MSE_OPER oper;
+ tBTA_MSE_MA_STATE state; /* state machine state */
+
+} tBTA_MSE_MA_SESS_CB;
+
+typedef struct
+{
+ tBTA_MSE_MA_SESS_CB sess_cb[BTA_MSE_NUM_SESS];
+ UINT32 sdp_handle; /* SDP record handle */
+ char *p_rootpath;
+ tOBX_HANDLE obx_handle; /* OBEX handle ID */
+ BOOLEAN stopping;
+ BOOLEAN in_use;
+ tBTA_SEC sec_mask;
+ tBTA_MA_MSG_TYPE sup_msg_type;
+ char servicename[BTA_SERVICE_NAME_LEN + 1];
+ UINT8 scn; /* SCN of the MA server */
+ tBTA_MA_INST_ID mas_inst_id; /* MAS instance id */
+}tBTA_MSE_MA_CB;
+
+/* state machine states */
+enum
+{
+ BTA_MSE_MN_IDLE_ST = 0, /* Idle */
+ BTA_MSE_MN_W4_CONN_ST, /* wait for connection state */
+ BTA_MSE_MN_CONN_ST, /* Connected - MAS Session is active */
+ BTA_MSE_MN_CLOSING_ST /* Closing is in progress */
+};
+typedef UINT8 tBTA_MSE_MN_STATE;
+
+/* notification registration status */
+typedef struct
+{
+ BOOLEAN status;
+ tBTA_MA_INST_ID mas_inst_id; /* only valid when status == TRUE*/
+} tBTA_MSE_MN_REG_STATUS;
+
+/* Message notification report */
+typedef struct
+{
+ UINT16 buffer_len;
+ UINT16 bytes_sent;
+ BOOLEAN final_pkt;
+ UINT8 pkt_cnt;
+ tBTA_MA_INST_ID mas_instance_id;
+ UINT8 *p_buffer;
+}tBTA_MSE_MN_MSG_NOTIF;
+
+typedef struct
+{
+ tBTA_MSE_MN_REG_STATUS notif_reg[BTA_MSE_NUM_INST];
+ tBTA_MSE_OBX_PKT obx; /* Holds the current OBX packet information */
+ tBTA_MSE_MN_MSG_NOTIF msg_notif;
+ TIMER_LIST_ENT rsp_timer; /* response timer */
+ tSDP_DISCOVERY_DB *p_db; /* pointer to discovery database */
+ tSDP_DISC_CMPL_CB *sdp_cback;
+ tOBX_HANDLE obx_handle;
+ UINT16 sdp_service;
+ UINT16 peer_mtu;
+ BOOLEAN in_use;
+ BOOLEAN req_pending; /* TRUE when waiting for an obex response */
+ BOOLEAN cout_active; /* TRUE if call-out is currently active */
+ BOOLEAN sdp_pending;
+ BD_ADDR bd_addr; /* Peer device MNS server address */
+ tBTA_MSE_MN_STATE state; /* state machine state */
+ tBTA_SEC sec_mask;
+ UINT8 timer_oper; /* current active response timer action (abort or close) */
+ UINT8 obx_oper; /* current active OBX operation PUT or GET operations */
+ UINT8 aborting;
+}tBTA_MSE_MN_CB;
+
+typedef struct
+{
+ BOOLEAN in_use;
+ BD_ADDR bd_addr;
+ BOOLEAN opened;
+ BOOLEAN busy;
+}tBTA_MSE_PM_CB;
+
+
+typedef struct
+{
+ tBTA_MSE_MA_CB scb[BTA_MSE_NUM_INST]; /* MA Server Control Blocks */
+ tBTA_MSE_MN_CB ccb[BTA_MSE_NUM_MN]; /* MN Client Control Blocks */
+ tBTA_MSE_PM_CB pcb[BTA_MSE_NUM_MN];
+ tBTA_MSE_CBACK *p_cback; /* pointer to application event callback function */
+ BOOLEAN enable;
+ BOOLEAN disabling;
+ UINT8 app_id;
+}tBTA_MSE_CB;
+
+/******************************************************************************
+** Configuration Definitions
+*******************************************************************************/
+/* Configuration structure */
+typedef struct
+{
+ INT32 abort_tout; /* Timeout in milliseconds to wait for abort OBEX response (client only) */
+ INT32 stop_tout; /* Timeout in milliseconds to wait for close OBEX response (client only) */
+
+} tBTA_MSE_MA_CFG;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* MAS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_MSE_CB bta_mse_cb;
+#else
+extern tBTA_MSE_CB *bta_mse_cb_ptr;
+ #define bta_mse_cb (*bta_mse_cb_ptr)
+#endif
+
+#define BTA_MSE_GET_INST_CB_PTR(inst_idx) &(bta_mse_cb.scb[(inst_idx)])
+#define BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx ) &(bta_mse_cb.scb[(inst_idx)].sess_cb[(sess_idx)])
+#define BTA_MSE_GET_MN_CB_PTR(ccb_idx) &(bta_mse_cb.ccb[(ccb_idx)])
+#define BTA_MSE_GET_PM_CB_PTR(pcb_idx) &(bta_mse_cb.pcb[(pcb_idx)])
+/* MAS configuration constants */
+extern tBTA_MSE_MA_CFG * p_bta_ms_cfg;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+/* MSE event handler for MA and MN */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ extern BOOLEAN bta_mse_hdl_event(BT_HDR *p_msg);
+
+/* State machine drivers */
+ extern void bta_mse_ma_sm_execute(UINT8 inst_idx, UINT8 sess_idx, UINT16 event, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_sm_execute(UINT8 ccb_idx, UINT16 event, tBTA_MSE_DATA *p_data);
+
+ extern void bta_mse_ma_sdp_register (tBTA_MSE_MA_CB *p_scb, char *p_service_name, tBTA_MA_INST_ID inst_id, tBTA_MA_MSG_TYPE msg_type);
+
+/* Obx callback functions */
+ extern void bta_mse_ma_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt);
+
+ extern void bta_mse_mn_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event, UINT8 rsp_code,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt);
+
+/* action functions for MA */
+ extern void bta_mse_ma_int_close(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_api_accessrsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_api_upd_ibx_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_api_set_notif_reg_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+
+ extern void bta_mse_ma_ci_get_folder_entry(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_ci_get_ml_info(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_ci_get_ml_entry(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_ci_get_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_ci_push_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_ci_del_msg(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+
+ extern void bta_mse_ma_obx_disc(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_obx_connect(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_obx_close(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_obx_abort(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_obx_put(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_obx_get(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_obx_setpath(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_conn_err_rsp(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_ma_close_complete(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+
+/* action function for MN */
+ extern void bta_mse_mn_init_sdp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_start_client(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_stop_client(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_obx_conn_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_close(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_send_notif(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_rsp_timeout(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_put_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_obx_tout(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_close_compl(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_ignore_obx(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_sdp_fail(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_abort(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+ extern void bta_mse_mn_abort_rsp(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+
+
+/* miscellaneous functions */
+ extern void bta_mse_discard_data(UINT16 event, tBTA_MSE_DATA *p_data);
+
+/* utility functions */
+
+ extern void bta_mse_send_push_msg_in_prog_evt(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_send_get_msg_in_prog_evt(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_send_oper_cmpl_evt(UINT8 inst_idx, UINT8 sess_idx, tBTA_MA_STATUS status);
+ extern void bta_mse_pushmsg(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN first_pkt);
+ extern void bta_mse_clean_set_msg_sts(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_clean_set_notif_reg(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_clean_push_msg(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_init_set_msg_sts(UINT8 inst_idx, UINT8 sess_idx, UINT8 *p_rsp_code);
+ extern void bta_mse_init_push_msg(UINT8 inst_idx, UINT8 sess_idx, UINT8 *p_rsp_code);
+ extern void bta_mse_remove_uuid(void);
+ extern void bta_mse_clean_mas_service(UINT8 inst_idx);
+ extern void bta_mse_abort_too_late(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_clean_getput(UINT8 inst_idx, UINT8 sess_idx, tBTA_MA_STATUS status);
+ extern void bta_mse_clean_msg(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_end_of_msg(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code);
+ extern void bta_mse_getmsg(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req);
+ extern tBTA_MA_STATUS bta_mse_build_msg_listing_obj(tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry,
+ UINT16 *p_size, char *p_buf );
+ extern void bta_mse_clean_msg_list(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_end_of_msg_list(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code);
+ extern UINT8 bta_mse_add_msg_list_info(UINT8 inst_idx, UINT8 sess_idx);
+ extern UINT8 bta_mse_add_msg_list_entry(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_getmsglist(UINT8 inst_idx, UINT8 sess_idx,BOOLEAN new_req);
+ extern UINT8 * bta_mse_read_app_params(BT_HDR *p_pkt, UINT8 tag, UINT16 *param_len);
+ extern void bta_mse_clean_list(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_end_of_list(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code);
+ extern UINT8 bta_mse_add_list_entry(UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_getfolderlist(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req);
+ extern UINT8 bta_mse_chdir(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_OPER *p_oper);
+ extern BOOLEAN bta_mse_send_set_notif_reg(UINT8 status,
+ UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_proc_notif_reg_status(UINT8 status,
+ UINT8 inst_idx, UINT8 sess_idx);
+ extern void bta_mse_discard_data(UINT16 event, tBTA_MSE_DATA *p_data);
+ extern BOOLEAN bta_mse_find_bd_addr_match_sess_cb_idx(BD_ADDR bd_addr, UINT8 inst_idx, UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_mas_inst_id_match_cb_idx(tBTA_MA_INST_ID mas_inst_id, UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_handle_match_mas_inst_cb_idx(tOBX_HANDLE obx_handle, UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_mas_sess_cb_idx(tOBX_HANDLE obx_handle, UINT8 *p_mas_inst_idx, UINT8 *p_mas_sess_idx);
+ extern BOOLEAN bta_mse_find_ma_cb_indexes(tBTA_MSE_DATA *p_msg, UINT8 *p_inst_idx, UINT8 *p_sess_idx);
+ extern void bta_mse_ma_cleanup(tBTA_MSE_DATA *p_msg);
+ extern BOOLEAN bta_mse_is_a_duplicate_id(tBTA_MA_INST_ID mas_inst_id);
+ extern BOOLEAN bta_mse_find_avail_mas_inst_cb_idx(UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_avail_mas_sess_cb_idx(tBTA_MSE_MA_CB *p_scb, UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_sess_id_match_ma_cb_indexes(tBTA_MA_SESS_HANDLE mas_session_id,
+ UINT8 *p_inst_idx, UINT8 *p_sess_idx);
+ extern BOOLEAN bta_mse_find_avail_mn_cb_idx(UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_bd_addr_match_mn_cb_index(BD_ADDR p_bd_addr, UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_sess_id_match_mn_cb_index(tBTA_MA_SESS_HANDLE mas_session_id,
+ UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_mn_cb_index(tBTA_MSE_DATA *p_msg, UINT8 *p_ccb_idx);
+ extern void bta_mse_mn_cleanup(tBTA_MSE_DATA *p_msg);
+ extern tBTA_MA_STATUS bta_mse_build_map_event_rpt_obj(tBTA_MSE_NOTIF_TYPE notif_type,
+ tBTA_MA_MSG_HANDLE handle,
+ char * p_folder,
+ char * p_old_folder,
+ tBTA_MA_MSG_TYPE msg_typ,
+ UINT16 * p_len,
+ UINT8 * p_buffer);
+ extern void bta_mse_mn_start_timer(UINT8 ccb_idx, UINT8 timer_id);
+ extern void bta_mse_mn_stop_timer(UINT8 ccb_idx, UINT8 timer_id);
+ extern BOOLEAN bta_mse_mn_add_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id);
+ extern BOOLEAN bta_mse_mn_remove_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id);
+ extern void bta_mse_mn_remove_all_inst_ids(UINT8 ccb_idx);
+ extern UINT8 bta_mse_mn_find_num_of_act_inst_id(UINT8 ccb_idx);
+ extern BOOLEAN bta_mse_mn_is_inst_id_exist(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id );
+ extern BOOLEAN bta_mse_mn_is_ok_to_close_mn(BD_ADDR bd_addr, tBTA_MA_INST_ID mas_inst_id );
+ extern BOOLEAN bta_mse_mn_get_first_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID *p_mas_inst_id);
+ extern tBTA_MA_STATUS bta_mse_mn_cont_send_notif(UINT8 ccb_idx, BOOLEAN first_pkt);
+ extern void bta_mse_mn_send_notif_evt(tBTA_MA_INST_ID mas_instance_id, tBTA_MA_STATUS status,
+ BD_ADDR bd_addr );
+ extern void bta_mse_mn_clean_send_notif(UINT8 ccb_idx);
+ extern void bta_mse_ma_fl_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt);
+ extern void bta_mse_ma_ml_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt);
+ extern BOOLEAN bta_mse_ma_msg_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt);
+ extern BOOLEAN bta_mse_get_msglist_path(UINT8 inst_idx, UINT8 sess_idx);
+
+ extern BOOLEAN bta_mse_find_pm_cb_index(BD_ADDR p_bd_addr, UINT8 *p_idx);
+ extern BOOLEAN bta_mse_find_avail_pm_cb_idx(UINT8 *p_idx);
+ extern void bta_mse_pm_conn_open(BD_ADDR bd_addr);
+ extern void bta_mse_pm_conn_close(BD_ADDR bd_addr);
+ extern void bta_mse_set_ma_oper(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_OPER oper);
+ extern void bta_mse_set_mn_oper(UINT8 ccb_idx, UINT8 oper);
+#ifdef __cplusplus
+}
+#endif
+#endif /* BTA_MSE_INT_H */
diff --git a/bta/ma/bta_mse_main.c b/bta/ma/bta_mse_main.c
new file mode 100644
index 0000000..feddd09
--- /dev/null
+++ b/bta/ma/bta_mse_main.c
@@ -0,0 +1,1367 @@
+/*****************************************************************************
+**
+** Name: bta_mse_main.c
+**
+** Description: This file contains the Message Access Server main functions
+** and state machine.
+**
+** Copyright (c) 1998-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_fs_api.h"
+#include "bta_mse_int.h"
+#include "gki.h"
+#include "utl.h"
+#include "obx_api.h"
+
+/*****************************************************************************
+** Message Access Server State Table
+*****************************************************************************/
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+/* state machine action enumeration list for MAS */
+enum
+{
+ BTA_MSE_MA_INT_CLOSE,
+ BTA_MSE_MA_API_ACCESSRSP,
+ BTA_MSE_MA_API_UPD_IBX_RSP,
+ BTA_MSE_MA_API_SET_NOTIF_REG_RSP,
+ BTA_MSE_MA_CI_GET_FENTRY,
+ BTA_MSE_MA_CI_GET_ML_INFO,
+ BTA_MSE_MA_CI_GET_ML_ENTRY,
+ BTA_MSE_MA_CI_GET_MSG,
+ BTA_MSE_MA_CI_PUSH_MSG,
+ BTA_MSE_MA_CI_DEL_MSG,
+ BTA_MSE_MA_OBX_CONNECT,
+ BTA_MSE_MA_OBX_DISC,
+ BTA_MSE_MA_OBX_CLOSE,
+ BTA_MSE_MA_OBX_ABORT,
+ BTA_MSE_MA_OBX_PUT,
+ BTA_MSE_MA_OBX_GET,
+ BTA_MSE_MA_OBX_SETPATH,
+ BTA_MSE_MA_CONN_ERR_RSP,
+ BTA_MSE_MA_CLOSE_COMPLETE,
+ BTA_MSE_MA_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_MSE_MA_ACTION)(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_DATA *p_data);
+
+/* action function list for MAS */
+const tBTA_MSE_MA_ACTION bta_mse_ma_action[] =
+{
+ bta_mse_ma_int_close,
+ bta_mse_ma_api_accessrsp,
+ bta_mse_ma_api_upd_ibx_rsp,
+ bta_mse_ma_api_set_notif_reg_rsp,
+ bta_mse_ma_ci_get_folder_entry,
+ bta_mse_ma_ci_get_ml_info,
+ bta_mse_ma_ci_get_ml_entry,
+ bta_mse_ma_ci_get_msg,
+ bta_mse_ma_ci_push_msg,
+ bta_mse_ma_ci_del_msg,
+ bta_mse_ma_obx_connect,
+ bta_mse_ma_obx_disc,
+ bta_mse_ma_obx_close,
+ bta_mse_ma_obx_abort,
+ bta_mse_ma_obx_put,
+ bta_mse_ma_obx_get,
+ bta_mse_ma_obx_setpath,
+ bta_mse_ma_conn_err_rsp,
+ bta_mse_ma_close_complete,
+};
+
+
+/* state table information */
+#define BTA_MSE_MA_ACTIONS 1 /* number of actions */
+#define BTA_MSE_MA_NEXT_STATE 1 /* position of next state */
+#define BTA_MSE_MA_NUM_COLS 2 /* number of columns in state tables */
+
+
+/* state table for MAS idle state */
+static const UINT8 bta_mse_ma_st_idle[][BTA_MSE_MA_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_MSE_INT_CLOSE_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_API_ACCESSRSP_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_API_UPD_IBX_RSP_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_API_SET_NOTIF_REG_RSP_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_INT_START_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+
+/* BTA_MSE_CI_GET_FENTRY_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_CI_GET_ML_INFO_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_CI_GET_ML_ENTRY_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_CI_GET_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_CI_PUSH_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_CI_DEL_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+
+/* BTA_MSE_MA_OBX_CONN_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_MA_OBX_DISC_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_MA_OBX_ABORT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_MA_OBX_CLOSE_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_MA_OBX_PUT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_MA_OBX_GET_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_MA_OBX_SETPATH_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+/* BTA_MSE_CLOSE_CMPL_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_IDLE_ST},
+};
+
+/* state table for obex/rfcomm connection state */
+static const UINT8 bta_mse_ma_st_listen[][BTA_MSE_MA_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_MSE_INT_CLOSE_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_API_ACCESSRSP_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_API_UPD_IBX_RSP_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_API_SET_NOTIF_REG_RSP_EVT*/{BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_MA_INT_START_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_CI_GET_FENTRY_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_CI_GET_ML_INFO_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_CI_GET_ML_ENTRY_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_CI_GET_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_CI_PUSH_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_CI_DEL_MSG_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_MA_OBX_CONN_EVT */ {BTA_MSE_MA_OBX_CONNECT, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_MA_OBX_DISC_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_MA_OBX_ABORT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_MA_OBX_CLOSE_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_MA_OBX_PUT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_MA_OBX_GET_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_MA_OBX_SETPATH_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+/* BTA_MSE_CLOSE_CMPL_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_LISTEN_ST},
+};
+
+/* state table for open state */
+static const UINT8 bta_mse_ma_st_connected[][BTA_MSE_MA_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_MSE_INT_CLOSE_EVT */ {BTA_MSE_MA_INT_CLOSE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_API_ACCESSRSP_EVT */ {BTA_MSE_MA_API_ACCESSRSP, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_API_UPD_IBX_RSP_EVT*/ {BTA_MSE_MA_API_UPD_IBX_RSP, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_API_SET_NOTIF_REG_RSP_EVT*/{BTA_MSE_MA_API_SET_NOTIF_REG_RSP,BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_MA_INT_START_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_CI_GET_FENTRY_EVT */ {BTA_MSE_MA_CI_GET_FENTRY, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_CI_GET_ML_INFO_EVT */ {BTA_MSE_MA_CI_GET_ML_INFO, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_CI_GET_ML_ENTRY_EVT*/ {BTA_MSE_MA_CI_GET_ML_ENTRY, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_CI_GET_MSG_EVT */ {BTA_MSE_MA_CI_GET_MSG, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_CI_PUSH_MSG_EVT */ {BTA_MSE_MA_CI_PUSH_MSG, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_CI_DEL_MSG_EVT */ {BTA_MSE_MA_CI_DEL_MSG, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_MA_OBX_CONN_EVT */ {BTA_MSE_MA_CONN_ERR_RSP, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_MA_OBX_DISC_EVT */ {BTA_MSE_MA_OBX_DISC, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_ABORT_EVT */ {BTA_MSE_MA_OBX_ABORT, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_MA_OBX_CLOSE_EVT */ {BTA_MSE_MA_OBX_CLOSE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_PUT_EVT */ {BTA_MSE_MA_OBX_PUT, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_MA_OBX_GET_EVT */ {BTA_MSE_MA_OBX_GET, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_MA_OBX_SETPATH_EVT*/ {BTA_MSE_MA_OBX_SETPATH, BTA_MSE_MA_CONN_ST},
+/* BTA_MSE_CLOSE_CMPL_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CONN_ST},
+};
+
+/* state table for closing state */
+static const UINT8 bta_mse_ma_st_closing[][BTA_MSE_MA_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_MSE_INT_CLOSE_EVT */ {BTA_MSE_MA_INT_CLOSE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_API_ACCESSRSP_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_API_UPD_IBX_RSP_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_API_SET_NOTIF_REG_RSP_EVT*/{BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_INT_START_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_CI_GET_FENTRY_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_CI_GET_ML_INFO_EVT*/ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_CI_GET_ML_ENTRY_EVT*/ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_CI_GET_MSG_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_CI_PUSH_MSG_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_CI_DEL_MSG_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_CONN_EVT */ {BTA_MSE_MA_CONN_ERR_RSP, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_DISC_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_ABORT_EVT */ {BTA_MSE_MA_OBX_ABORT, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_CLOSE_EVT */ {BTA_MSE_MA_OBX_CLOSE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_PUT_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_GET_EVT */ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_MA_OBX_SETPATH_EVT*/ {BTA_MSE_MA_IGNORE, BTA_MSE_MA_CLOSING_ST},
+/* BTA_MSE_CLOSE_CMPL_EVT */ {BTA_MSE_MA_CLOSE_COMPLETE, BTA_MSE_MA_LISTEN_ST},
+};
+
+/* type for state table MAS */
+typedef const UINT8 (*tBTA_MSE_MA_ST_TBL)[BTA_MSE_MA_NUM_COLS];
+
+/* MAS state table */
+const tBTA_MSE_MA_ST_TBL bta_mse_ma_st_tbl[] =
+{
+ bta_mse_ma_st_idle,
+ bta_mse_ma_st_listen,
+ bta_mse_ma_st_connected,
+ bta_mse_ma_st_closing
+};
+
+/*****************************************************************************
+** Message Notification Client State Table
+*****************************************************************************/
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+/* state machine action enumeration list for MNC */
+/* The order of this enumeration must be the same as bta_mse_mn_act_tbl[] */
+enum
+{
+ BTA_MSE_MN_INIT_SDP,
+ BTA_MSE_MN_START_CLIENT,
+ BTA_MSE_MN_STOP_CLIENT,
+ BTA_MSE_MN_OBX_CONN_RSP,
+ BTA_MSE_MN_CLOSE,
+ BTA_MSE_MN_SEND_NOTIF,
+ BTA_MSE_MN_RSP_TIMEOUT,
+ BTA_MSE_MN_PUT_RSP,
+ BTA_MSE_MN_OBX_TOUT,
+ BTA_MSE_MN_CLOSE_COMPL,
+ BTA_MSE_MN_ABORT,
+ BTA_MSE_MN_ABORT_RSP,
+ BTA_MSE_MN_SDP_FAIL,
+ BTA_MSE_MN_IGNORE_OBX,
+ BTA_MSE_MN_IGNORE
+};
+
+typedef void (*tBTA_MSE_MN_ACTION)(UINT8 ccb_idx, tBTA_MSE_DATA *p_data);
+
+static const tBTA_MSE_MN_ACTION bta_mse_mn_action[] =
+{
+ bta_mse_mn_init_sdp,
+ bta_mse_mn_start_client,
+ bta_mse_mn_stop_client,
+ bta_mse_mn_obx_conn_rsp,
+ bta_mse_mn_close,
+ bta_mse_mn_send_notif,
+ bta_mse_mn_rsp_timeout,
+ bta_mse_mn_put_rsp,
+ bta_mse_mn_obx_tout,
+ bta_mse_mn_close_compl,
+ bta_mse_mn_abort,
+ bta_mse_mn_abort_rsp,
+ bta_mse_mn_sdp_fail,
+ bta_mse_mn_ignore_obx
+};
+
+
+/* state table information */
+#define BTA_MSE_MN_ACTIONS 1 /* number of actions */
+#define BTA_MSE_MN_ACTION_COL 0 /* position of action */
+#define BTA_MSE_MN_NEXT_STATE 1 /* position of next state */
+#define BTA_MSE_MN_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_mse_mn_st_idle[][BTA_MSE_MN_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_MSE_MN_INT_OPEN_EVT */ {BTA_MSE_MN_INIT_SDP, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_MN_INT_CLOSE_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_SDP_OK_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_SDP_FAIL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_OBX_CONN_RSP_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_OBX_PUT_RSP_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_OBX_CLOSE_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_OBX_TOUT_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_CLOSE_CMPL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_API_SEND_NOTIF_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_API_MN_ABORT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_OBX_ABORT_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_RSP_TOUT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_IDLE_ST}
+};
+
+
+/* state table for wait for authentication state */
+static const UINT8 bta_mse_mn_st_w4_conn[][BTA_MSE_MN_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_MSE_MN_INT_OPEN_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_MN_INT_CLOSE_EVT */ {BTA_MSE_MN_STOP_CLIENT, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_SDP_OK_EVT */ {BTA_MSE_MN_START_CLIENT, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_MN_SDP_FAIL_EVT */ {BTA_MSE_MN_SDP_FAIL, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_MN_OBX_CONN_RSP_EVT */ {BTA_MSE_MN_OBX_CONN_RSP, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_OBX_PUT_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_MN_OBX_CLOSE_EVT */ {BTA_MSE_MN_CLOSE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_OBX_TOUT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_MN_CLOSE_CMPL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_API_SEND_NOTIF_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_API_MN_ABORT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_MN_OBX_ABORT_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST},
+/* BTA_MSE_MN_RSP_TOUT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_W4_CONN_ST}
+};
+
+/* state table for connected state */
+static const UINT8 bta_mse_mn_st_connected[][BTA_MSE_MN_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_MSE_MN_INT_OPEN_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_INT_CLOSE_EVT */ {BTA_MSE_MN_STOP_CLIENT, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_SDP_OK_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_SDP_FAIL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_OBX_CONN_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_OBX_PUT_RSP_EVT */ {BTA_MSE_MN_PUT_RSP, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_OBX_CLOSE_EVT */ {BTA_MSE_MN_CLOSE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_OBX_TOUT_EVT */ {BTA_MSE_MN_OBX_TOUT, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_CLOSE_CMPL_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_API_SEND_NOTIF_EVT */ {BTA_MSE_MN_SEND_NOTIF, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_API_MN_ABORT_EVT */ {BTA_MSE_MN_ABORT, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_OBX_ABORT_RSP_EVT */ {BTA_MSE_MN_ABORT_RSP, BTA_MSE_MN_CONN_ST},
+/* BTA_MSE_MN_RSP_TOUT_EVT */ {BTA_MSE_MN_RSP_TIMEOUT, BTA_MSE_MN_CLOSING_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_mse_mn_st_closing[][BTA_MSE_MN_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_MSE_MN_INT_OPEN_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_INT_CLOSE_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_SDP_OK_EVT */ {BTA_MSE_MN_CLOSE_COMPL, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_SDP_FAIL_EVT */ {BTA_MSE_MN_CLOSE_COMPL, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_MN_OBX_CONN_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_OBX_PUT_RSP_EVT */ {BTA_MSE_MN_IGNORE_OBX, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_OBX_CLOSE_EVT */ {BTA_MSE_MN_CLOSE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_OBX_TOUT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_CLOSE_CMPL_EVT */ {BTA_MSE_MN_CLOSE_COMPL, BTA_MSE_MN_IDLE_ST},
+/* BTA_MSE_API_SEND_NOTIF_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_API_MN_ABORT_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_OBX_ABORT_RSP_EVT */ {BTA_MSE_MN_IGNORE, BTA_MSE_MN_CLOSING_ST},
+/* BTA_MSE_MN_RSP_TOUT_EVT */ {BTA_MSE_MN_RSP_TIMEOUT, BTA_MSE_MN_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_MSE_MN_ST_TBL)[BTA_MSE_MN_NUM_COLS];
+
+/* state table */
+const tBTA_MSE_MN_ST_TBL bta_mse_mn_st_tbl[] =
+{
+ bta_mse_mn_st_idle,
+ bta_mse_mn_st_w4_conn,
+ bta_mse_mn_st_connected,
+ bta_mse_mn_st_closing
+};
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* MSE control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_MSE_CB bta_mse_cb;
+#endif
+
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+
+static char *bta_mse_evt_code(tBTA_MSE_INT_EVT evt_code);
+static char *bta_mse_ma_state_code(tBTA_MSE_MA_STATE state_code);
+static char *bta_mse_mn_state_code(tBTA_MSE_MN_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_sm_execute
+**
+** Description State machine event handling function for MA
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** event - MA event
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_sm_execute(UINT8 inst_idx, UINT8 sess_idx, UINT16 event, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MA_ST_TBL state_table;
+ UINT8 action;
+ int i;
+ tBTA_MSE_MA_SESS_CB *p_cb = &(bta_mse_cb.scb[inst_idx].sess_cb[sess_idx]);
+
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ tBTA_MSE_MA_STATE in_state = p_cb->state;
+ UINT16 cur_evt = event;
+ APPL_TRACE_EVENT3("MSE MA Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ bta_mse_ma_state_code(in_state),
+ bta_mse_evt_code(cur_evt));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_mse_ma_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_MSE_MA_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_MSE_MA_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_MSE_MA_IGNORE)
+ {
+ (*bta_mse_ma_action[action])(inst_idx, sess_idx, p_data);
+ }
+ else
+ {
+ /* discard mas data */
+ bta_mse_discard_data(p_data->hdr.event, p_data);
+ break;
+ }
+ }
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ if (in_state != p_cb->state)
+ {
+ APPL_TRACE_EVENT3("MSE MA State Change: [%s] -> [%s] after Event [%s]",
+ bta_mse_ma_state_code(in_state),
+ bta_mse_ma_state_code(p_cb->state),
+ bta_mse_evt_code(cur_evt));
+ }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_sm_execute
+**
+** Description State machine event handling function for MNC
+**
+** Parameters mn_cb_idx - Index to the MN control block
+** event - MN event
+** p_data - Pointer to the event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_sm_execute(UINT8 mn_cb_idx, UINT16 event, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_CB *p_cb = &(bta_mse_cb.ccb[mn_cb_idx]);
+ tBTA_MSE_MN_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+
+
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ tBTA_MSE_MN_STATE in_state = p_cb->state;
+ UINT16 cur_evt = event;
+ APPL_TRACE_EVENT3("MSE MN Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ bta_mse_mn_state_code(in_state),
+ bta_mse_evt_code(cur_evt));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_mse_mn_st_tbl[p_cb->state];
+ event -= BTA_MSE_MN_EVT_MIN;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_MSE_MN_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_MSE_MN_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_MSE_MN_IGNORE)
+ {
+ (*bta_mse_mn_action[action])(mn_cb_idx, p_data);
+ }
+ else
+ {
+ /* discard mas data */
+ bta_mse_discard_data(p_data->hdr.event, p_data);
+ break;
+ }
+ }
+
+
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+ if (in_state != p_cb->state)
+ {
+ APPL_TRACE_EVENT3("MSE MN State Change: [%s] -> [%s] after Event [%s]",
+ bta_mse_mn_state_code(in_state),
+ bta_mse_mn_state_code(p_cb->state),
+ bta_mse_evt_code(cur_evt));
+ }
+#endif
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_enable
+**
+** Description Process API enable request to enable MCE subsystem
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_ma_api_enable(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE evt_data;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_ma_api_enable" );
+#endif
+ /* If already enabled then reject this request */
+ if (p_cb->enable)
+ {
+ APPL_TRACE_ERROR0("MSE is already enabled");
+ evt_data.enable.app_id = p_data->api_enable.app_id;
+ evt_data.enable.status = BTA_MA_STATUS_FAIL;
+ p_data->api_enable.p_cback(BTA_MSE_ENABLE_EVT, (tBTA_MSE *) &evt_data);
+ return;
+ }
+
+ /* Done with checking. now perform the enable oepration*/
+ /* initialize control block */
+ memset(p_cb, 0, sizeof(tBTA_MSE_CB));
+
+ p_cb->p_cback = p_data->api_enable.p_cback;
+ p_cb->app_id = p_data->api_enable.app_id;
+ p_cb->enable = TRUE;
+
+ evt_data.enable.app_id = p_cb->app_id;
+ evt_data.enable.status = BTA_MA_STATUS_OK;
+ p_cb->p_cback(BTA_MSE_ENABLE_EVT, (tBTA_MSE *) &evt_data);
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_disable
+**
+** Description Process API disable request
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_ma_api_disable(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE evt_data;
+ tBTA_MA_STATUS status = BTA_MA_STATUS_OK;
+ UINT8 app_id = p_data->api_disable.app_id;
+ UINT8 i,j, num_act_mas=0, num_act_sess=0;
+ tBTA_MSE_MA_CB *p_scb;
+ tBTA_MSE_MA_SESS_CB *p_sess_cb;
+ BOOLEAN send_disable_evt =FALSE;
+ tBTA_MSE_MN_CB *p_ccb;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_ma_api_disable" );
+#endif
+
+ if (p_cb->enable)
+ {
+ /* close all MN connections */
+ for (i=0; i < BTA_MSE_NUM_MN; i ++)
+ {
+ p_ccb = BTA_MSE_GET_MN_CB_PTR(i);
+ if (p_ccb->in_use &&
+ (p_ccb->state != BTA_MSE_MN_IDLE_ST))
+ {
+ bta_mse_mn_remove_all_inst_ids(i);
+ bta_mse_mn_sm_execute(i,BTA_MSE_MN_INT_CLOSE_EVT, NULL);
+ }
+ }
+
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ p_scb = BTA_MSE_GET_INST_CB_PTR(i);
+ if (p_scb->in_use )
+ {
+ num_act_mas++;
+ p_cb->disabling = TRUE;
+ p_scb->stopping = TRUE;
+ num_act_sess =0;
+ for (j=0; j<BTA_MSE_NUM_SESS; j++ )
+ {
+ p_sess_cb = BTA_MSE_GET_SESS_CB_PTR(i, j);
+ if (p_sess_cb->state != BTA_MSE_MA_LISTEN_ST)
+ {
+ bta_mse_ma_sm_execute(i, j, BTA_MSE_INT_CLOSE_EVT, p_data);
+ num_act_sess++;
+ }
+ }
+
+ if (!num_act_sess)
+ {
+ evt_data.stop.status = BTA_MA_STATUS_OK;
+ evt_data.stop.mas_instance_id = p_scb->mas_inst_id;
+ p_cb->p_cback(BTA_MSE_STOP_EVT, (tBTA_MSE *) &evt_data);
+ bta_mse_clean_mas_service(i);
+ num_act_mas--;
+ }
+ }
+ }
+
+ if (!num_act_mas)
+ {
+ send_disable_evt = TRUE;
+ p_cb->enable = FALSE;
+ }
+ }
+ else
+ {
+ send_disable_evt = TRUE;
+ status = BTA_MA_STATUS_FAIL;
+ }
+
+
+ if (send_disable_evt)
+ {
+ evt_data.enable.app_id = app_id;
+ evt_data.enable.status = status;
+ p_cb->p_cback(BTA_MSE_DISABLE_EVT, (tBTA_MSE *) &evt_data);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("MSE Disabled location-1");
+#endif
+ }
+
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_start
+**
+** Description Process API MA server start request
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_ma_api_start(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ UINT8 i = 0;
+ tBTA_MSE evt_data; /* event call back */
+ tBTA_MSE_MA_CB *p_scb = NULL; /* MA instance control block*/
+ tOBX_StartParams start_msg;
+ tBTA_MSE_API_START *p_api = &p_data->api_start;
+ tOBX_TARGET target;
+ tOBX_STATUS status;
+ tBTA_UTL_COD cod;
+ UINT8 mas_instance_idx;
+ UINT16 root_folder_len;
+ tBTA_MA_STATUS ma_status = BTA_MA_STATUS_OK;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_ma_api_start" );
+#endif
+ if (!p_cb->enable || ((p_cb->enable) && bta_mse_is_a_duplicate_id(p_api->mas_inst_id)) )
+ {
+ ma_status = BTA_MA_STATUS_DUPLICATE_ID;
+ }
+
+ if ((ma_status == BTA_MA_STATUS_OK) && bta_mse_find_avail_mas_inst_cb_idx(&mas_instance_idx))
+ {
+ APPL_TRACE_EVENT1("bta_mse_ma_api_start inst_idx=%d",mas_instance_idx );
+
+ /* initialize the MA Instance control block */
+ p_scb = &(p_cb->scb[mas_instance_idx]);
+ memset(p_scb, 0, sizeof(tBTA_MSE_MA_CB));
+
+ p_scb->in_use = TRUE;
+ BCM_STRNCPY_S(p_scb->servicename, sizeof(p_scb->servicename), p_api->servicename, BTA_SERVICE_NAME_LEN);
+ p_scb->mas_inst_id = p_api->mas_inst_id;
+ p_scb->sec_mask = p_api->sec_mask;
+ p_scb->sup_msg_type = p_api->sup_msg_type;
+
+ /* If directory is specified set the length */
+ root_folder_len = p_bta_fs_cfg->max_path_len + 1;
+
+ /* Allocate an aligned memory buffer to hold the root path in the */
+ /* MAS instance cb as well as the session cbs */
+ /* Add 1 byte for '\0' */
+ if ((p_scb->p_rootpath = (char *)GKI_getbuf((UINT16)(root_folder_len+1))) != NULL)
+ {
+ memcpy(target.target, BTA_MAS_MESSAGE_ACCESS_TARGET_UUID, BTA_MAS_UUID_LENGTH);
+ target.len = BTA_MAS_UUID_LENGTH;
+ p_scb->scn = BTM_AllocateSCN();
+ BCM_STRNCPY_S(p_scb->p_rootpath, root_folder_len+1, p_api->p_root_path, root_folder_len);
+ p_scb->p_rootpath[root_folder_len] = '\0';
+
+ /* Register MAP security requirements with BTM */
+ BTM_SetSecurityLevel(FALSE, p_api->servicename, BTM_SEC_SERVICE_MAP,
+ p_api->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, (UINT32)p_scb->scn);
+
+ /* Start up the MSE service */
+ memset(&start_msg, 0, sizeof(tOBX_StartParams));
+ start_msg.p_target = &target;
+ /* Make the MTU fit into one RFC frame */
+ start_msg.mtu = OBX_MAX_MTU;
+ start_msg.scn = p_scb->scn;
+ start_msg.authenticate = FALSE; /* OBX authentication is disabled */
+ start_msg.auth_option = (UINT8) NULL;
+ start_msg.p_cback = bta_mse_ma_obx_cback;
+ start_msg.realm_len =(UINT8) NULL;
+ start_msg.p_realm = (UINT8) NULL;
+ start_msg.realm_charset = (tOBX_CHARSET) NULL;
+ start_msg.max_sessions = BTA_MSE_NUM_SESS;
+
+ if ((status = OBX_StartServer (&start_msg, &p_scb->obx_handle)) == OBX_SUCCESS)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("Obx start for MAS server: obx_hdl=%d", p_scb->obx_handle);
+#endif
+ /* initialze all session states */
+ for (i=0; i<BTA_MSE_NUM_SESS; i++ )
+ {
+ p_scb->sess_cb[i].state = BTA_MSE_MA_LISTEN_ST;
+ }
+
+ if (ma_status == BTA_MA_STATUS_OK)
+ {
+ /* Set the File Transfer service class bit */
+ cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
+ utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+
+ /* Set up the SDP record for pbs service */
+ bta_mse_ma_sdp_register(p_scb, p_api->servicename, p_scb->mas_inst_id, p_scb->sup_msg_type );
+ }
+ else
+ {
+ /* release resources */
+ OBX_StopServer(p_scb->obx_handle);
+ for (i=0; i < BTA_MSE_NUM_SESS; i++ )
+ {
+ utl_freebuf((void**)&p_scb->sess_cb[i].p_workdir );
+ }
+ }
+ }
+ else
+ {
+ /* release resources */
+ utl_freebuf((void**)&p_scb->p_rootpath);
+ APPL_TRACE_ERROR1("OBX_StartServer returns error (%d)", status);
+ ma_status = BTA_MA_STATUS_NO_RESOURCE;
+ }
+ }
+ else /* Cannot allocate resources to run Server */
+ {
+ APPL_TRACE_ERROR0("Not enough Resources to run MSE Server");
+ ma_status = BTA_MA_STATUS_NO_RESOURCE;
+ }
+
+ if (ma_status != BTA_MA_STATUS_OK)
+ {
+ /* clearn up the contrl block*/
+ memset(p_scb, 0, sizeof(tBTA_MSE_MA_CB));
+ }
+ }
+
+ evt_data.start.mas_instance_id = p_api->mas_inst_id;
+ evt_data.start.status = ma_status;
+ p_cb->p_cback(BTA_MSE_START_EVT, (tBTA_MSE *) &evt_data);
+
+}
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_stop
+**
+** Description Process API MA server stop request
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_ma_api_stop(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_API_STOP *p_stop = &p_data->api_stop;
+ BOOLEAN send_stop_evt = FALSE;
+ tBTA_MA_STATUS status = BTA_MA_STATUS_OK;
+ tBTA_MSE_MA_CB *p_scb;
+ tBTA_MSE_MA_SESS_CB *p_sess_cb;
+ tBTA_MSE_MN_CB *p_ccb;
+ UINT8 i, inst_idx;
+ UINT8 num_act_sess=0;
+ tBTA_MSE evt_data;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_ma_api_stop" );
+#endif
+
+
+ if (bta_mse_find_mas_inst_id_match_cb_idx(p_stop->mas_inst_id, &inst_idx))
+ {
+ p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ p_scb->stopping = TRUE;
+
+ for (i=0; i < BTA_MSE_NUM_MN; i ++)
+ {
+ p_ccb = BTA_MSE_GET_MN_CB_PTR(i);
+ if (p_ccb->in_use &&
+ (p_ccb->state != BTA_MSE_MN_IDLE_ST) &&
+ bta_mse_mn_is_ok_to_close_mn(p_ccb->bd_addr,p_scb->mas_inst_id))
+ {
+ /* close the MN connection if mas_inst_id is the last active inst_id */
+ bta_mse_mn_remove_inst_id(i, p_scb->mas_inst_id);
+ bta_mse_mn_sm_execute(i,BTA_MSE_MN_INT_CLOSE_EVT, NULL);
+ }
+ }
+ /* close all active session */
+ for (i=0; i < BTA_MSE_NUM_SESS; i ++)
+ {
+ p_sess_cb = &(p_scb->sess_cb[i]);
+ if (p_sess_cb->state != BTA_MSE_MA_LISTEN_ST)
+ {
+ APPL_TRACE_EVENT2("Send API CLOSE to SM for STOP sess ind=%d state=%d",i,p_sess_cb->state);
+ bta_mse_ma_sm_execute(inst_idx, i, BTA_MSE_INT_CLOSE_EVT, p_data);
+ num_act_sess++;
+ }
+ }
+
+ if (!num_act_sess)
+ {
+ bta_mse_clean_mas_service(inst_idx);
+ send_stop_evt = TRUE;
+ }
+ }
+ else
+ {
+ send_stop_evt = TRUE;
+ status = BTA_MA_STATUS_FAIL;
+ }
+
+ if (send_stop_evt)
+ {
+ evt_data.stop.status = status;
+ evt_data.stop.mas_instance_id = p_stop->mas_inst_id;
+ p_cb->p_cback(BTA_MSE_STOP_EVT, (tBTA_MSE *) &evt_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_close
+**
+** Description Process API close request. It will close all MA
+** sesions on the specified MAS instance ID
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_ma_api_close(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_API_CLOSE *p_close = &p_data->api_close;
+ BOOLEAN send_close_evt = FALSE;
+ tBTA_MA_STATUS status = BTA_MA_STATUS_OK;
+ tBTA_MSE_MA_CB *p_scb;
+ tBTA_MSE_MA_SESS_CB *p_sess_cb;
+ UINT8 i, inst_idx;
+ UINT8 num_act_sess=0;
+ tBTA_MSE evt_data;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_ma_api_close" );
+#endif
+ if (bta_mse_find_mas_inst_id_match_cb_idx(p_close->mas_instance_id, &inst_idx))
+ {
+ p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ /* close all active sessions for the specified MA Server */
+ for (i=0; i < BTA_MSE_NUM_SESS; i ++)
+ {
+ p_sess_cb = &(p_scb->sess_cb[i]);
+ if (p_sess_cb->state != BTA_MSE_MA_LISTEN_ST)
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT4("Disconnect inst_id=%d, sess_id=%d, inst_idx=%d, sess_idx=%d",
+ p_close->mas_instance_id,
+ p_sess_cb->obx_handle,
+ inst_idx,
+ i);
+#endif
+
+ bta_mse_ma_sm_execute(inst_idx, i, BTA_MSE_INT_CLOSE_EVT, p_data);
+ num_act_sess++;
+ }
+ }
+
+ if (!num_act_sess)
+ {
+ send_close_evt = TRUE;
+ }
+ }
+ else
+ {
+ send_close_evt = TRUE;
+ status = BTA_MA_STATUS_FAIL;
+ }
+
+ if (send_close_evt)
+ {
+ evt_data.ma_close.status = status;
+ evt_data.ma_close.mas_session_id = 0;
+ evt_data.ma_close.mas_instance_id = p_close->mas_instance_id ;
+ p_cb->p_cback(BTA_MSE_MA_CLOSE_EVT, (tBTA_MSE *) &evt_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_api_ma_close
+**
+** Description Process API MA close request. It will close the
+** specified MA session.
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_ma_api_ma_close(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_API_MA_CLOSE *p_ma_close = &p_data->api_ma_close;
+ UINT8 inst_idx, sess_idx;
+ tBTA_MSE evt_data;
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_ma_api_ma_close" );
+#endif
+
+ if (bta_mse_find_mas_inst_id_match_cb_idx (p_ma_close->mas_instance_id, &inst_idx)&&
+ bta_mse_find_bd_addr_match_sess_cb_idx(p_ma_close->bd_addr,inst_idx,&sess_idx))
+ {
+ bta_mse_ma_sm_execute(inst_idx, sess_idx, BTA_MSE_INT_CLOSE_EVT, p_data);
+ }
+ else
+ {
+ evt_data.ma_close.mas_session_id = 0xFF;
+ evt_data.ma_close.mas_instance_id = p_ma_close->mas_instance_id;
+ evt_data.ma_close.status = BTA_MA_STATUS_FAIL ;
+ p_cb->p_cback(BTA_MSE_MA_CLOSE_EVT, (tBTA_MSE *) &evt_data);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_api_close
+**
+** Description Process API MN close request.
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_mn_api_close(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_API_MN_CLOSE *p_mn_close = &p_data->api_mn_close;
+ UINT8 ccb_idx;
+ tBTA_MSE evt_data;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_mn_api_close" );
+#endif
+
+ if (bta_mse_find_bd_addr_match_mn_cb_index(p_mn_close->bd_addr, &ccb_idx))
+ {
+ bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_INT_CLOSE_EVT, p_data);
+ }
+ else
+ {
+ evt_data.mn_close.bd_addr[0] = '\0';
+ evt_data.mn_close.dev_name[0] = '\0';
+ p_cb->p_cback(BTA_MSE_MN_CLOSE_EVT, (tBTA_MSE *) &evt_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_api_send_notif
+**
+** Description Process API send message notification report to all MCEs
+** registered with the specified MAS instance ID
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_mn_api_send_notif(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_API_SEND_NOTIF *p_mn_send_notif = &p_data->mn_send_notif;
+ UINT8 i;
+ tBTA_MSE evt_data;
+ tBTA_MSE_MN_CB *p_ccb;
+ UINT8 active_sess_cnt;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_mn_api_send_notif" );
+#endif
+
+ active_sess_cnt =0 ;
+ for (i=0; i < BTA_MSE_NUM_MN; i ++)
+ {
+ p_ccb = BTA_MSE_GET_MN_CB_PTR(i);
+
+ if (p_ccb->in_use &&
+ (p_ccb->state == BTA_MSE_MN_CONN_ST) &&
+ (memcmp(p_ccb->bd_addr, p_mn_send_notif->except_bd_addr, BD_ADDR_LEN) != 0 ) &&
+ bta_mse_mn_is_inst_id_exist(i,p_mn_send_notif->mas_instance_id))
+ {
+ bta_mse_mn_sm_execute(i, BTA_MSE_API_SEND_NOTIF_EVT, p_data);
+ active_sess_cnt++;
+ }
+ }
+
+ if (!active_sess_cnt)
+ {
+ evt_data.send_notif.mas_instance_id = p_mn_send_notif->mas_instance_id;
+ evt_data.send_notif.status = BTA_MA_STATUS_FAIL;
+ memset(evt_data.send_notif.bd_addr,0, sizeof(evt_data.send_notif.bd_addr));
+ p_cb->p_cback(BTA_MSE_SEND_NOTIF_EVT, (tBTA_MSE *) &evt_data);
+ }
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_api_abort
+**
+** Description Abort the current OBEX multi-packet oepration
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_mn_api_abort(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ tBTA_MSE_MN_API_ABORT *p_mn_abort = &p_data->mn_abort;
+ UINT8 i;
+ tBTA_MSE_MN_CB *p_ccb;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_mn_api_abort" );
+#endif
+
+ for (i=0; i < BTA_MSE_NUM_MN; i ++)
+ {
+ p_ccb = BTA_MSE_GET_MN_CB_PTR(i);
+ if (p_ccb->in_use &&
+ (p_ccb->state == BTA_MSE_MN_CONN_ST) &&
+ bta_mse_mn_is_inst_id_exist(i,p_mn_abort->mas_instance_id))
+ {
+ bta_mse_mn_sm_execute(i, BTA_MSE_API_MN_ABORT_EVT, p_data);
+ }
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_rsp_tout
+**
+** Description Process MN response timer timeout event
+**
+** Parameters p_cb - Pointer to MSE control block
+** p_data - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_mse_mn_rsp_tout(tBTA_MSE_CB *p_cb, tBTA_MSE_DATA *p_data)
+{
+ UINT8 ccb_idx;
+
+ ccb_idx = (UINT8)(p_data->hdr.event - BTA_MSE_MN_RSP0_TOUT_EVT);
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_rsp_tout ccd_idx=%d",ccb_idx);
+#endif
+ bta_mse_mn_sm_execute(ccb_idx, BTA_MSE_MN_RSP_TOUT_EVT, p_data);
+}
+/*******************************************************************************
+**
+** Function bta_mse_hdl_event
+**
+** Description MSE main event handling function.
+**
+** Parameters p_msg - Pointer to MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_mse_hdl_event(BT_HDR *p_msg){
+ UINT8 inst_idx, sess_idx, ccb_idx;
+ BOOLEAN success = TRUE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("MSE Event Handler: Event [%s]",
+ bta_mse_evt_code(p_msg->event));
+#endif
+
+ switch (p_msg->event)
+ {
+ case BTA_MSE_API_ENABLE_EVT:
+ bta_mse_ma_api_enable(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_API_START_EVT:
+ bta_mse_ma_api_start(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_API_STOP_EVT:
+ bta_mse_ma_api_stop(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_API_DISABLE_EVT:
+ bta_mse_ma_api_disable(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_API_CLOSE_EVT:
+ bta_mse_ma_api_close(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_API_MA_CLOSE_EVT:
+ bta_mse_ma_api_ma_close(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_API_MN_CLOSE_EVT:
+ bta_mse_mn_api_close(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_API_SEND_NOTIF_EVT:
+ bta_mse_mn_api_send_notif(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_API_MN_ABORT_EVT:
+ bta_mse_mn_api_abort(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ case BTA_MSE_MN_RSP0_TOUT_EVT:
+ case BTA_MSE_MN_RSP1_TOUT_EVT:
+ case BTA_MSE_MN_RSP2_TOUT_EVT:
+ case BTA_MSE_MN_RSP3_TOUT_EVT:
+ case BTA_MSE_MN_RSP4_TOUT_EVT:
+ case BTA_MSE_MN_RSP5_TOUT_EVT:
+ case BTA_MSE_MN_RSP6_TOUT_EVT:
+ bta_mse_mn_rsp_tout(&bta_mse_cb, (tBTA_MSE_DATA *) p_msg);
+ break;
+
+ default:
+
+ if (p_msg->event < BTA_MSE_MN_EVT_MIN)
+ {
+ if (bta_mse_find_ma_cb_indexes((tBTA_MSE_DATA *) p_msg, &inst_idx, &sess_idx))
+ {
+ bta_mse_ma_sm_execute( inst_idx ,
+ sess_idx ,
+ p_msg->event, (tBTA_MSE_DATA *) p_msg);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("unable to find inst_idx and sess_idx: event=%s",
+ bta_mse_evt_code(p_msg->event));
+ success = FALSE;
+ bta_mse_ma_cleanup ((tBTA_MSE_DATA *) p_msg);
+ }
+ }
+ else
+ {
+ if (bta_mse_find_mn_cb_index((tBTA_MSE_DATA *) p_msg, &ccb_idx))
+ {
+ bta_mse_mn_sm_execute( ccb_idx,
+ p_msg->event ,
+ (tBTA_MSE_DATA *) p_msg);
+ }
+ else
+ {
+ APPL_TRACE_ERROR1("unable to find ccb_idx: event=%s",
+ bta_mse_evt_code(p_msg->event));
+ success = FALSE;
+ bta_mse_mn_cleanup ((tBTA_MSE_DATA *) p_msg);
+ }
+ }
+ break;
+ }
+
+ return(success);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if (BTA_MSE_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+/*******************************************************************************
+**
+** Function bta_mse_ma_evt_code
+**
+** Description Maps MA event code to the corresponding event string
+**
+** Parameters evt_code - MA event code
+**
+** Returns string pointer for the associated event name
+**
+*******************************************************************************/
+static char *bta_mse_evt_code(tBTA_MSE_INT_EVT evt_code){
+ switch (evt_code)
+ {
+ case BTA_MSE_API_CLOSE_EVT:
+ return "BTA_MSE_API_CLOSE_EVT";
+ case BTA_MSE_API_MA_CLOSE_EVT:
+ return "BTA_MSE_API_MA_CLOSE_EVT";
+ case BTA_MSE_API_MN_CLOSE_EVT:
+ return "BTA_MSE_API_MN_CLOSE_EVT";
+ case BTA_MSE_INT_CLOSE_EVT:
+ return "BTA_MSE_INT_CLOSE_EVT";
+ case BTA_MSE_API_ACCESSRSP_EVT:
+ return "BTA_MSE_API_ACCESSRSP_EVT";
+ case BTA_MSE_API_UPD_IBX_RSP_EVT:
+ return "BTA_MSE_API_UPD_IBX_RSP_EVT";
+ case BTA_MSE_API_SET_NOTIF_REG_RSP_EVT:
+ return "BTA_MSE_API_SET_NOTIF_REG_RSP_EVT";
+ case BTA_MSE_INT_START_EVT:
+ return "BTA_MSE_INT_START_EVT";
+ case BTA_MSE_CI_GET_FENTRY_EVT:
+ return "BTA_MSE_CI_GET_FENTRY_EVT";
+ case BTA_MSE_CI_GET_ML_INFO_EVT:
+ return "BTA_MSE_CI_GET_ML_INFO_EVT";
+ case BTA_MSE_CI_GET_ML_ENTRY_EVT:
+ return "BTA_MSE_CI_GET_ML_ENTRY_EVT";
+ case BTA_MSE_CI_GET_MSG_EVT:
+ return "BTA_MSE_CI_GET_MSG_EVT";
+ case BTA_MSE_CI_PUSH_MSG_EVT:
+ return "BTA_MSE_CI_PUSH_MSG_EVT";
+ case BTA_MSE_CI_DEL_MSG_EVT:
+ return "BTA_MSE_CI_DEL_MSG_EVT";
+ case BTA_MSE_MA_OBX_CONN_EVT:
+ return "BTA_MSE_MA_OBX_CONN_EVT";
+ case BTA_MSE_MA_OBX_DISC_EVT:
+ return "BTA_MSE_MA_OBX_DISC_EVT";
+ case BTA_MSE_MA_OBX_ABORT_EVT:
+ return "BTA_MSE_MA_OBX_ABORT_EVT";
+ case BTA_MSE_MA_OBX_CLOSE_EVT:
+ return "BTA_MSE_MA_OBX_CLOSE_EVT";
+ case BTA_MSE_MA_OBX_PUT_EVT:
+ return "BTA_MSE_MA_OBX_PUT_EVT";
+ case BTA_MSE_MA_OBX_GET_EVT:
+ return "BTA_MSE_MA_OBX_GET_EVT";
+ case BTA_MSE_MA_OBX_SETPATH_EVT:
+ return "BTA_MSE_MA_OBX_SETPATH_EVT";
+ case BTA_MSE_CLOSE_CMPL_EVT:
+ return "BTA_MSE_CLOSE_CMPL_EVT";
+ case BTA_MSE_MN_INT_OPEN_EVT:
+ return "BTA_MSE_MN_INT_OPEN_EVT";
+ case BTA_MSE_MN_INT_CLOSE_EVT:
+ return "BTA_MSE_MN_INT_CLOSE_EVT";
+ case BTA_MSE_MN_SDP_OK_EVT:
+ return "BTA_MSE_MN_SDP_OK_EVT";
+ case BTA_MSE_MN_SDP_FAIL_EVT:
+ return "BTA_MSE_MN_SDP_FAIL_EVT";
+ case BTA_MSE_MN_OBX_CONN_RSP_EVT:
+ return "BTA_MSE_MN_OBX_CONN_RSP_EVT";
+ case BTA_MSE_MN_OBX_PUT_RSP_EVT:
+ return "BTA_MSE_MN_OBX_PUT_RSP_EVT";
+ case BTA_MSE_MN_OBX_CLOSE_EVT:
+ return "BTA_MSE_MN_OBX_CLOSE_EVT";
+ case BTA_MSE_MN_OBX_TOUT_EVT:
+ return "BTA_MSE_MN_OBX_TOUT_EVT";
+ case BTA_MSE_MN_CLOSE_CMPL_EVT:
+ return "BTA_MSE_MN_CLOSE_CMPL_EVT";
+ case BTA_MSE_API_SEND_NOTIF_EVT:
+ return "BTA_MSE_API_SEND_NOTIF_EVT";
+ case BTA_MSE_API_MN_ABORT_EVT:
+ return "BTA_MSE_API_MN_ABORT_EVT";
+ case BTA_MSE_MN_OBX_ABORT_RSP_EVT:
+ return "BTA_MSE_MN_OBX_ABORT_RSP_EVT";
+ case BTA_MSE_API_ENABLE_EVT:
+ return "BTA_MSE_API_ENABLE_EVT";
+ case BTA_MSE_API_START_EVT:
+ return "BTA_MSE_API_START_EVT";
+ case BTA_MSE_API_STOP_EVT:
+ return "BTA_MSE_API_STOP_EVT";
+ default:
+ return "Unknown MSE event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_state_code
+**
+** Description Maps MA state code to the corresponding state string
+**
+** Parameters state_code - MA state code
+**
+** Returns string pointer for the associated state name
+**
+*******************************************************************************/
+static char *bta_mse_ma_state_code(tBTA_MSE_MA_STATE state_code){
+ switch (state_code)
+ {
+ case BTA_MSE_MA_IDLE_ST:
+ return "BTA_MSE_MA_IDLE_ST";
+ case BTA_MSE_MA_LISTEN_ST:
+ return "BTA_MSE_MA_LISTEN_ST";
+ case BTA_MSE_MA_CONN_ST:
+ return "BTA_MSE_MA_CONN_ST";
+ case BTA_MSE_MA_CLOSING_ST:
+ return "BTA_MSE_MA_CLOSING_ST";
+ default:
+ return "Unknown MA state code";
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_state_code
+**
+** Description Maps MN state code to the corresponding state string
+**
+** Parameters state_code - MN state code
+**
+** Returns string pointer for the associated state name
+**
+*******************************************************************************/
+static char *bta_mse_mn_state_code(tBTA_MSE_MN_STATE state_code){
+ switch (state_code)
+ {
+ case BTA_MSE_MN_IDLE_ST:
+ return "BTA_MSE_MN_IDLE_ST";
+ case BTA_MSE_MN_W4_CONN_ST:
+ return "BTA_MSE_MN_W4_CONN_ST";
+ case BTA_MSE_MN_CONN_ST:
+ return "BTA_MSE_MN_CONN_ST";
+ case BTA_MSE_MN_CLOSING_ST:
+ return "BTA_MSE_MN_CLOSING_ST";
+ default:
+ return "Unknown MN state code";
+ }
+}
+
+#endif /* Debug Functions */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#endif /* BTA_MSE_INCLUDED */
diff --git a/bta/ma/bta_mse_sdp.c b/bta/ma/bta_mse_sdp.c
new file mode 100644
index 0000000..a56e07f
--- /dev/null
+++ b/bta/ma/bta_mse_sdp.c
@@ -0,0 +1,63 @@
+/*****************************************************************************
+**
+** Name: bta_mse_sdp.c
+**
+** File: Implements the SDP functions used by Message Access Server
+**
+** Copyright (c) 1998-2009, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <string.h>
+
+#include "sdp_api.h"
+#include "bta_mse_int.h"
+#include "goep_util.h"
+
+/*****************************************************************************
+**
+** Function: bta_mas_sdp_register
+**
+** Purpose: Register the Message Access service 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
+**
+*****************************************************************************/
+void bta_mse_ma_sdp_register (tBTA_MSE_MA_CB *p_cb, char *p_service_name,
+ tBTA_MA_INST_ID inst_id,
+ tBTA_MA_MSG_TYPE msg_type)
+{
+ UINT16 mas_service = UUID_SERVCLASS_MESSAGE_ACCESS;
+ tGOEP_ERRORS goep_status;
+
+ goep_status = GOEP_Register(p_service_name, &p_cb->sdp_handle, p_cb->scn,
+ 1, &mas_service, UUID_SERVCLASS_MAP_PROFILE,
+ BTA_MAS_DEFAULT_VERSION);
+ if (goep_status == GOEP_SUCCESS)
+ {
+ /* add instance ID */
+ SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_MAS_INSTANCE_ID, UINT_DESC_TYPE,
+ (UINT32)1, (UINT8*)&inst_id);
+
+ /* add supported message type */
+ SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_SUPPORTED_MSG_TYPE, UINT_DESC_TYPE,
+ (UINT32)1, (UINT8*)&msg_type);
+
+ bta_sys_add_uuid(mas_service); /* UUID_SERVCLASS_MESSAGE_ACCESS */
+ APPL_TRACE_DEBUG1("MAS: SDP Registered (handle 0x%08x)", p_cb->sdp_handle);
+ }
+ else
+ {
+ if (p_cb->sdp_handle) SDP_DeleteRecord(p_cb->sdp_handle);
+ APPL_TRACE_ERROR0("bta_mse_ma_sdp_register FAILED");
+ }
+
+ return;
+}
diff --git a/bta/ma/bta_mse_utils.c b/bta/ma/bta_mse_utils.c
new file mode 100644
index 0000000..2b14b7a
--- /dev/null
+++ b/bta/ma/bta_mse_utils.c
@@ -0,0 +1,3867 @@
+/*********************************************a********************************
+**
+** Name: bta_mse_utils.c
+**
+** Description: This file implements utility functions for the
+** file transfer server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_MSE_INCLUDED) && (BTA_MSE_INCLUDED == TRUE)
+
+#include <stdio.h>
+#include <string.h>
+#include "gki.h"
+#include "utl.h"
+#include "bd.h"
+#include "bta_fs_api.h"
+#include "bta_mse_int.h"
+#include "bta_fs_co.h"
+#include "bta_mse_co.h"
+
+#include "bta_ma_util.h"
+
+
+/*******************************************************************************
+* Macros for MSE
+*******************************************************************************/
+#define BTA_MSE_XML_EOL "\n"
+#define BTA_MSE_FOLDER_LISTING_START ( "<?xml version=\"1.0\"?>\n" \
+ "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">\n" \
+ "<folder-listing version=\"1.0\">\n" )
+
+#define BTA_MSE_FOLDER_LISTING_END ( "</folder-listing>" )
+#define BTA_MSE_PARENT_FOLDER (" <parent-folder/>\n")
+
+#define BTA_MSE_FILE_ELEM "file"
+#define BTA_MSE_FOLDER_ELEM "folder"
+#define BTA_MSE_NAME_ATTR "name"
+#define BTA_MSE_SIZE_ATTR "size"
+#define BTA_MSE_TYPE_ATTR "type"
+#define BTA_MSE_MODIFIED_ATTR "modified"
+#define BTA_MSE_CREATED_ATTR "created"
+#define BTA_MSE_ACCESSED_ATTR "accessed"
+#define BTA_MSE_USER_PERM_ATTR "user-perm"
+
+#define BTA_MSE_MSG_LISTING_START ( "<MAP-msg-listing version=\"1.0\">\n" )
+#define BTA_MSE_MSG_LISTING_END ( "</MAP-msg-listing>" )
+
+
+// btla-specific ++
+#define BTA_MSE_ENABLE_FS_CO FALSE
+// btla-specific --
+
+/*******************************************************************************
+**
+** Function bta_mse_send_push_msg_in_prog_evt
+**
+** Description send the push message in progress event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+
+void bta_mse_send_push_msg_in_prog_evt(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg;
+ tBTA_MSE cback_evt_data;
+ tBTA_MSE *p_data = &cback_evt_data;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_send_push_msg_in_prog_evt inst_idx=%d sess_idx=%d",
+ inst_idx,sess_idx);
+#endif
+
+ p_data->push_msg_in_prog.mas_session_id = p_cb->obx_handle;
+ p_data->push_msg_in_prog.bytes = p_cb->obx.offset;
+ p_data->push_msg_in_prog.obj_size = p_push_msg->push_byte_cnt;
+ bta_mse_cb.p_cback(BTA_MSE_PUSH_MSG_IN_PROG_EVT, (tBTA_MSE *) p_data);
+}
+/*******************************************************************************
+**
+** Function bta_mse_send_get_msg_in_prog_evt
+**
+** Description Sends the get message in progress event
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_send_get_msg_in_prog_evt(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param;
+ tBTA_MSE cback_evt_data;
+ tBTA_MSE *p_data = &cback_evt_data;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_send_get_msg_in_prog_evt inst_idx=%d sess_idx=%d",
+ inst_idx,sess_idx);
+#endif
+
+ p_data->get_msg_in_prog.mas_session_id = (tBTA_MA_SESS_HANDLE) p_cb->obx_handle;
+ p_data->get_msg_in_prog.bytes = p_param->filled_buff_size;
+ p_data->get_msg_in_prog.obj_size = p_param->byte_get_cnt;
+ bta_mse_cb.p_cback(BTA_MSE_GET_MSG_IN_PROG_EVT, (tBTA_MSE *) p_data);
+}
+/*******************************************************************************
+**
+** Function bta_mse_send_oper_cmpl_evt
+**
+** Description Sends the operartion complete event based on the specified status
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** status - MA status code
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_send_oper_cmpl_evt(UINT8 inst_idx, UINT8 sess_idx, tBTA_MA_STATUS status)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param;
+ tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg;
+ tBTA_MSE cback_evt_data;
+ tBTA_MSE *p_data = &cback_evt_data;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("bta_mse_send_oper_cmpl_evt inst_idx=%d sess_idx=%d status=%d",
+ inst_idx, sess_idx, status);
+#endif
+
+ p_data->oper_cmpl.mas_session_id = p_cb->obx_handle;
+ p_data->oper_cmpl.operation = p_cb->oper;
+ p_data->oper_cmpl.status = status;
+ switch (p_cb->oper)
+ {
+ case BTA_MSE_OPER_GET_MSG:
+ p_data->oper_cmpl.obj_size = p_param->byte_get_cnt;
+ break;
+ case BTA_MSE_OPER_PUSH_MSG:
+ p_data->oper_cmpl.obj_size = p_push_msg->push_byte_cnt;
+ break;
+ default:
+ p_data->oper_cmpl.obj_size = 0;
+ break;
+ }
+ bta_mse_cb.p_cback(BTA_MSE_OPER_CMPL_EVT, (tBTA_MSE *) p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_pushmsg
+**
+** Description Process the push message request
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** first_pkt - first packet of the push message request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_pushmsg(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN first_pkt)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg;
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MA_MPKT_STATUS mpkt_status;
+
+ p_push_msg->push_byte_cnt += p_obx->offset;
+ p_cb->cout_active = TRUE;
+ mpkt_status = BTA_MA_MPKT_STATUS_LAST;
+ if (!p_obx->final_pkt) mpkt_status = BTA_MA_MPKT_STATUS_MORE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT5("bta_mse_pushmsg i_idx=%d s_idx=%d first=%d final=%d cnt=%d",
+ inst_idx, sess_idx, first_pkt, p_obx->final_pkt,
+ p_push_msg->push_byte_cnt);
+#endif
+
+
+ bta_mse_co_push_msg((tBTA_MA_SESS_HANDLE) p_cb->obx_handle, &p_push_msg->param,
+ p_obx->offset, p_obx->p_start, first_pkt,
+ mpkt_status, BTA_MSE_CI_PUSH_MSG_EVT, bta_mse_cb.app_id);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_clean_set_msg_sts
+**
+** Description Cleans up the set message status resources and cotrol block
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_clean_set_msg_sts(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_SET_MSG_STS *p_set_msg_sts = &p_cb->set_msg_sts;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_clean_set_msg_sts");
+#endif
+
+ utl_freebuf((void**)&(p_set_msg_sts->p_msg_handle));
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_clean_set_notif_reg
+**
+** Description Cleans up the set notification registration resources and cotrol block
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_clean_set_notif_reg(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_clean_set_notif_reg");
+#endif
+
+ p_cb->notif_reg_req.notif_status_rcv = FALSE;
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_clean_push_msg
+**
+** Description Cleans up the push message resources and cotrol block
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_clean_push_msg(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_clean_push_msg");
+#endif
+
+ utl_freebuf((void**)&(p_push_msg->param.p_folder));
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_init_set_msg_sts
+**
+** Description Initializes the set message status resources and cotrol block
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_rsp_code - (output) pointer to the obex response code
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_init_set_msg_sts(UINT8 inst_idx, UINT8 sess_idx, UINT8 *p_rsp_code)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_SET_MSG_STS *p_set_msg_sts = &p_cb->set_msg_sts;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_init_set_msg_sts");
+#endif
+ *p_rsp_code = OBX_RSP_OK;
+
+
+
+ p_set_msg_sts->rcv_msg_handle = FALSE;
+ p_set_msg_sts->rcv_sts_ind = FALSE;
+ p_set_msg_sts->rcv_sts_val = FALSE;
+
+ if (!p_set_msg_sts->p_msg_handle)
+ {
+ if ((p_set_msg_sts->p_msg_handle = (char *)GKI_getbuf((UINT16)(BTA_MSE_64BIT_HEX_STR_SIZE))) == NULL )
+ {
+ *p_rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_init_push_msg
+**
+** Description initializes the push message resources and control block
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_rsp_code - (output) pointer to the obex response code
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_init_push_msg(UINT8 inst_idx, UINT8 sess_idx, UINT8 *p_rsp_code)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OPER_PUSH_MSG *p_push_msg = &p_cb->push_msg;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_init_push_msg");
+#endif
+ *p_rsp_code = OBX_RSP_OK;
+
+
+ p_push_msg->push_byte_cnt = 0;
+ p_push_msg->first_req_pkt = TRUE;
+ p_push_msg->rcv_charset = FALSE;
+ p_push_msg->rcv_folder_name = FALSE;
+ p_push_msg->rcv_retry = FALSE;
+ p_push_msg->rcv_transparent = FALSE;
+ p_push_msg->param.transparent = BTA_MA_TRANSP_OFF;
+ p_push_msg->param.retry = BTA_MA_RETRY_OFF;
+
+ if (!p_push_msg->param.p_folder)
+ {
+ if ((p_push_msg->param.p_folder = (char *)GKI_getbuf((UINT16)(p_bta_mse_cfg->max_name_len + 1))) == NULL )
+ {
+ *p_rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_remove_uuid
+**
+** Description Remove UUID and clear service
+**
+** Parameters none
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_remove_uuid(void)
+{
+ bta_sys_remove_uuid(UUID_SERVCLASS_MESSAGE_ACCESS);
+ BTM_SecClrService(BTM_SEC_SERVICE_MAP);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_clean_mas_service
+**
+** Description Cleans up the MAS service resources and control block
+**
+** Parameters inst_idx - Index to the MA instance control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_clean_mas_service(UINT8 inst_idx)
+{
+ tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ tBTA_MSE_MA_SESS_CB *p_cb;
+ int i, num_act_mas =0;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_clean_mas_service");
+#endif
+ OBX_StopServer(p_scb->obx_handle);
+ BTM_FreeSCN(p_scb->scn);
+ if (p_scb->sdp_handle) SDP_DeleteRecord(p_scb->sdp_handle);
+
+ utl_freebuf((void**)&p_scb->p_rootpath);
+ for (i=0; i < BTA_MSE_NUM_SESS; i++ )
+ {
+ p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, i);
+ utl_freebuf((void**)&p_cb->p_workdir);
+ }
+ p_scb->in_use = FALSE;
+
+ /* check all other MAS instances */
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ p_scb = BTA_MSE_GET_INST_CB_PTR(i);
+ if (p_scb->in_use) num_act_mas++;
+ }
+
+ if (!num_act_mas) bta_mse_remove_uuid();
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_abort_too_late
+**
+** Description It is too late to abort the operation
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_abort_too_late(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_abort_too_late oper=%d ",p_cb->oper );
+#endif
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_FORBIDDEN, (BT_HDR *)NULL);
+ p_cb->aborting = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_clean_getput
+**
+** Description Cleans up get and put resources and control blocks
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** status - operation status
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_clean_getput(UINT8 inst_idx, UINT8 sess_idx, tBTA_MA_STATUS status)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_clean_getput oper=%d status=%d",p_cb->oper, status );
+#endif
+ if (status == BTA_MA_STATUS_ABORTED)
+ {
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ p_cb->aborting = FALSE;
+ }
+ switch (p_cb->oper)
+ {
+ case BTA_MSE_OPER_UPDATE_INBOX:
+ bta_mse_set_ma_oper(inst_idx,sess_idx, BTA_MSE_OPER_NONE);
+ break;
+ case BTA_MSE_OPER_GET_FOLDER_LIST:
+ bta_mse_clean_list(inst_idx,sess_idx);
+ break;
+ case BTA_MSE_OPER_GET_MSG_LIST:
+ bta_mse_clean_msg_list(inst_idx,sess_idx);
+ break;
+ case BTA_MSE_OPER_GET_MSG:
+ bta_mse_send_oper_cmpl_evt(inst_idx,sess_idx, status);
+ bta_mse_clean_msg(inst_idx,sess_idx);
+ break;
+ case BTA_MSE_OPER_PUSH_MSG:
+ bta_mse_send_oper_cmpl_evt(inst_idx,sess_idx, status);
+ bta_mse_clean_push_msg(inst_idx,sess_idx);
+ break;
+ case BTA_MSE_OPER_DEL_MSG:
+ case BTA_MSE_OPER_SET_MSG_STATUS:
+ bta_mse_clean_set_msg_sts(inst_idx,sess_idx);
+ break;
+
+ default:
+ break;
+ }
+
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+ p_cb->obx.bytes_left = 0;
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_clean_msg
+**
+** Description Cleans up the get message resources and control block
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_clean_msg(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ /* Clean up control block */
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_clean_msg");
+#endif
+ utl_freebuf((void **)&p_cb->msg_param.p_msg_handle);
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_end_of_msg
+**
+** Description Complete the end body of the get message response, and
+** sends out the OBX get response
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** rsp_code - Obex response code
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_end_of_msg(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param;
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_end_of_msg");
+#endif
+ /* Add the end of folder listing string if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* If get message has completed, update the fraction delivery status */
+
+ if (p_param->add_frac_del_hdr)
+ {
+ *(p_param->p_frac_delivery) = p_param->frac_deliver_status;
+ p_param->add_frac_del_hdr = FALSE;
+ }
+
+ p_obx->offset += p_param->filled_buff_size;
+
+ if (rsp_code == OBX_RSP_OK)
+ {
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE);
+ }
+ else /* More data to be sent */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, FALSE);
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+
+ if (rsp_code == OBX_RSP_CONTINUE)
+ {
+ bta_mse_send_get_msg_in_prog_evt(inst_idx, sess_idx);
+ }
+ else
+ {
+ bta_mse_clean_getput(inst_idx, sess_idx, BTA_MA_STATUS_OK);
+ }
+ }
+ else /* An error occurred */
+ {
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_mse_clean_getput(inst_idx, sess_idx, BTA_MA_STATUS_FAIL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_getmsg
+**
+** Description Processes the get message request
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_getmsg(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_OPER_MSG_PARAM *p_param = &p_cb->msg_param;
+ UINT8 rsp_code = OBX_RSP_OK;
+ UINT8 *p, *p_start;
+ UINT16 len = 0;
+ BOOLEAN first_get=FALSE;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_getmsg");
+#endif
+
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /* p_cb->peer_mtu */ OBX_LRG_DATA_POOL_SIZE);
+ if (p_obx->p_pkt)
+ {
+ /* Is this a new request or continuation? */
+ if (new_req)
+ {
+ first_get = TRUE;
+ if (p_param->add_frac_del_hdr)
+ {
+ /* Add Fraction Deliver Header */
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ p = p_start;
+ *p++ = BTA_MA_APH_FRAC_DELVR;
+ *p++ = 1;
+ p_param->p_frac_delivery = p;
+ /* use Last as default and it can be changed to More if application indicates more */
+ UINT8_TO_BE_STREAM(p, BTA_MA_FRAC_DELIVER_LAST);
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+ }
+
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+ p_cb->cout_active = TRUE;
+ bta_mse_co_get_msg((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ &p_param->data,
+ first_get,
+ p_obx->bytes_left,
+ p_obx->p_start,
+ BTA_MSE_CI_GET_MSG_EVT,
+ bta_mse_cb.app_id);
+
+ /* List is not complete, so don't send the response yet */
+ rsp_code = OBX_RSP_PART_CONTENT;
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ /* Response goes out if complete or error occurred */
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_mse_end_of_msg(inst_idx, sess_idx,rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_clean_msg_list
+**
+** Description Cleans up the get message list resources and control block
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_clean_msg_list(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_MSGLIST *p_ml = &p_cb->ml;
+ /* Clean up control block */
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_clean_msg_list");
+#endif
+ bta_mse_set_ma_oper(inst_idx, sess_idx, BTA_MSE_OPER_NONE);
+ p_ml->remaing_size =0;
+ p_ml->offset =0;
+ p_ml->pending_ml_frag = FALSE;
+
+ utl_freebuf((void**)&p_ml->p_entry);
+ utl_freebuf((void**)&p_ml->p_info);
+ utl_freebuf((void**)&p_ml->p_xml_buf);
+ utl_freebuf((void**)&p_cb->ml_param.p_name);
+ utl_freebuf((void**)&p_cb->ml_param.p_path);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_end_of_msg_list
+**
+** Description Complete the end body of the get message listing response, and
+** sends out the OBX get response
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** rsp_code - Obex response code
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_end_of_msg_list(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_OPER_MLIST_PARAM *p_ml_param = &p_cb->ml_param;
+ UINT16 len;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_end_of_msg_list");
+#endif
+ /* Add the end of folder listing string if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* If listing has completed, check the max list count */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ if (p_ml_param->filter.max_list_cnt)
+ {
+ len = strlen(BTA_MSE_MSG_LISTING_END);
+ memcpy(&p_obx->p_start[p_obx->offset], BTA_MSE_MSG_LISTING_END, len);
+ p_obx->offset += len;
+
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE);
+ }
+
+ /* Clean up control block */
+ bta_mse_clean_msg_list(inst_idx, sess_idx);
+ }
+ else /* More listing data to be sent */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, FALSE);
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+ }
+ else /* An error occurred */
+ {
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_mse_clean_msg_list(inst_idx, sess_idx);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_add_msg_list_info
+**
+** Description Adds applications paramter headers for new message and
+** message list size
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns UINT8 - OBX response code
+** OBX_RSP_PART_CONTENT if not finished yet.
+**
+*******************************************************************************/
+UINT8 bta_mse_add_msg_list_info(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_MSGLIST *p_ml = &p_cb->ml;
+ tBTA_MSE_CO_MSG_LIST_INFO *p_info = p_ml->p_info;
+ tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry = p_ml->p_entry;
+ tBTA_MA_MSG_LIST_FILTER_PARAM *p_filter = &p_cb->ml_param.filter;
+ UINT8 rsp_code = OBX_RSP_PART_CONTENT;
+ UINT8 *p, *p_start;
+ UINT16 len = 0;
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_add_msg_list_info: new msg=%d, list size=%d",
+ p_info->new_msg, p_info->msg_list_size );
+#endif
+
+ /* add app params for GetMessageListing */
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ p = p_start;
+
+ *p++ = BTA_MA_APH_NEW_MSG;
+ *p++ = 1;
+ UINT8_TO_BE_STREAM(p, p_info->new_msg);
+
+ *p++ = BTA_MA_APH_MSG_LST_SIZE;
+ *p++ = 2;
+ UINT16_TO_BE_STREAM(p, p_info->msg_list_size);
+
+ *p++ = BTA_MA_APH_MSE_TIME;
+ *p++ = p_info->mse_time_len;
+ memcpy(p, p_info->mse_time, p_info->mse_time_len);
+ p += p_info->mse_time_len;
+
+ if (p != p_start)
+ {
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+
+ if (p_filter->max_list_cnt)
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ len = strlen(BTA_MSE_MSG_LISTING_START);
+ memcpy(&p_obx->p_start[p_obx->offset], BTA_MSE_MSG_LISTING_START, len);
+ p_obx->bytes_left -= (UINT16)(len + strlen(BTA_MSE_MSG_LISTING_END));
+ p_obx->offset += len;
+ p_cb->cout_active = TRUE;
+ bta_mse_co_get_msg_list_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ p_cb->ml_param.p_name,
+ p_filter, TRUE,
+ p_entry,
+ BTA_MSE_CI_GET_ML_ENTRY_EVT,
+ bta_mse_cb.app_id);
+ }
+ else
+ {
+ /* done with get msg list request */
+ rsp_code = OBX_RSP_OK;
+ }
+ return(rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_add_msg_list_entry
+**
+** Description Adds one entry of the message list to the message list object
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns UINT8 - OBX response code
+** OBX_RSP_PART_CONTENT if not finished yet.
+** OBX_RSP_CONTINUE [packet done]
+** Others send error response out
+**
+*******************************************************************************/
+UINT8 bta_mse_add_msg_list_entry(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_MSGLIST *p_ml = &p_cb->ml;
+ tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry = p_ml->p_entry;
+ tBTA_MA_MSG_LIST_FILTER_PARAM *p_filter = &p_cb->ml_param.filter;
+ char *p_buf;
+ UINT16 size;
+ UINT8 rsp_code = OBX_RSP_PART_CONTENT;
+ tBTA_MA_STATUS status;
+ BOOLEAN release_xml_buf = TRUE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_add_msg_list_entry");
+#endif
+
+ if (p_ml->pending_ml_frag)
+ {
+ if (p_ml->remaing_size <= p_obx->bytes_left)
+ {
+ size = p_ml->remaing_size;
+ p_ml->pending_ml_frag = FALSE;
+ }
+ else
+ {
+ rsp_code = OBX_RSP_CONTINUE;
+ size = p_obx->bytes_left;
+ }
+
+ p_buf = p_ml->p_xml_buf + p_ml->offset;
+ memcpy (&p_obx->p_start[p_obx->offset], p_buf, size);
+ p_obx->offset += size;
+ p_obx->bytes_left -= size;
+ p_ml->remaing_size -= size;
+ p_ml->offset += size;
+
+ if ( !p_ml->pending_ml_frag )
+ {
+ utl_freebuf((void **) &p_ml->p_xml_buf);
+ }
+
+
+ if (rsp_code == OBX_RSP_PART_CONTENT)
+ {
+ /* Get the next msg list entry */
+ p_cb->cout_active = TRUE;
+ bta_mse_co_get_msg_list_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ p_cb->ml_param.p_name,
+ p_filter, FALSE,
+ p_entry,
+ BTA_MSE_CI_GET_ML_ENTRY_EVT,
+ bta_mse_cb.app_id);
+ }
+ return rsp_code;
+ }
+
+ if ((p_buf = (char *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
+ {
+ p_buf[0] = '\0';
+ size = GKI_MAX_BUF_SIZE;
+ status = bta_mse_build_msg_listing_obj( p_entry, &size, p_buf );
+
+ if (status == BTA_MA_STATUS_OK)
+ {
+ size = strlen(p_buf);
+
+ if (size <= p_obx->bytes_left)
+ {
+ if ( size > 0)
+ {
+ memcpy (&p_obx->p_start[p_obx->offset], p_buf, size);
+ p_obx->offset += size;
+ p_obx->bytes_left -= size;
+ }
+
+ /* Get the next msg list entry */
+ p_cb->cout_active = TRUE;
+ bta_mse_co_get_msg_list_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ p_cb->ml_param.p_name,
+ p_filter, FALSE,
+ p_entry,
+ BTA_MSE_CI_GET_ML_ENTRY_EVT,
+ bta_mse_cb.app_id);
+ }
+ else /* entry did not fit in current obx packet; try to add entry in next obx req */
+ {
+ p_ml->pending_ml_frag = TRUE;
+ p_ml->p_xml_buf= p_buf;
+ p_ml->offset =0;
+ p_ml->remaing_size = size - p_obx->bytes_left;
+ p_ml->offset += p_obx->bytes_left;
+ release_xml_buf = FALSE;
+ memcpy (&p_obx->p_start[p_obx->offset], p_buf, p_obx->bytes_left);
+ p_obx->offset += p_obx->bytes_left;
+ p_obx->bytes_left = 0;
+
+ APPL_TRACE_EVENT2("1st msg list fragment peer_mtu=%d msg_list_size=%d",
+ p_cb->peer_mtu, size);
+ APPL_TRACE_EVENT3("pending_flag=%d offset=%d remaining_size=%d",
+ p_ml->pending_ml_frag, p_ml->offset, p_ml->remaing_size);
+ APPL_TRACE_EVENT2("obx offset=%d byte_left=%d",
+ p_obx->offset, p_obx->bytes_left );
+
+ rsp_code = OBX_RSP_CONTINUE;
+
+ }
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ /* Done with temporary buffer */
+ if (release_xml_buf) utl_freebuf((void **) &p_buf);
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ return(rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_getmsglist
+**
+** Description Process the retrieval of a msg listing.
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_mse_getmsglist(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_MSGLIST *p_ml = &p_cb->ml;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_getmsglist ");
+#endif
+
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /* p_cb->peer_mtu */ OBX_LRG_DATA_POOL_SIZE);
+ if (!p_ml->p_entry)
+ {
+ /* Allocate enough space for the structure */
+ p_ml->p_entry = (tBTA_MSE_CO_MSG_LIST_ENTRY *)
+ GKI_getbuf((UINT16)(sizeof(tBTA_MSE_CO_MSG_LIST_ENTRY)));
+ }
+
+ if (p_ml->p_entry && p_obx->p_pkt)
+ {
+ /* Is this a new request or continuation? */
+ if (new_req)
+ {
+ if (!p_ml->p_info)
+ {
+ /* Allocate enough space for the structure */
+ p_ml->p_info = (tBTA_MSE_CO_MSG_LIST_INFO *)
+ GKI_getbuf((UINT16)(sizeof(tBTA_MSE_CO_MSG_LIST_INFO)));
+ }
+
+ if (p_ml->p_info)
+ {
+ p_cb->ml_param.w4info =TRUE;
+
+ p_cb->cout_active = TRUE;
+ bta_mse_co_get_msg_list_info((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ p_cb->ml_param.p_name,
+ &(p_cb->ml_param.filter),
+ p_ml->p_info,
+ BTA_MSE_CI_GET_ML_INFO_EVT,
+ bta_mse_cb.app_id);
+
+ /* List is not complete, so don't send the response yet */
+ rsp_code = OBX_RSP_PART_CONTENT;
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ else /* Add the entry previously retrieved */
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+ rsp_code = bta_mse_add_msg_list_entry(inst_idx, sess_idx);
+ }
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ /* Response goes out if complete or error occurred */
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_mse_end_of_msg_list(inst_idx, sess_idx,rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_read_app_params
+**
+** Description Read the specified application parameter from the given OBX packet
+**
+** Parameters p_pkt - obex packet pointer
+** tag - application parameter tag
+** param_len - (output) pointer to the length of application paramter
+**
+** Returns pointer to the application parameter found
+** NULL - not found
+**
+*******************************************************************************/
+
+UINT8 * bta_mse_read_app_params(BT_HDR *p_pkt, UINT8 tag, UINT16 *param_len)
+{
+ UINT8 *p_data = NULL, *p = NULL;
+ UINT16 data_len = 0;
+ int left, len;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_read_app_params");
+#endif
+
+ if (OBX_ReadByteStrHdr(p_pkt, OBX_HI_APP_PARMS, &p_data, &data_len, 0))
+ {
+ left = data_len;
+ while (left > 0)
+ {
+ len = *(p_data + 1);
+ if (*p_data == tag)
+ {
+ p_data += 2;
+ p = p_data;
+ *param_len = (UINT16) len;
+ break;
+ }
+ p_data += (len+2);
+ left -= (len+2);
+ }
+ }
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_clean_list
+**
+** Description Cleans up the get folder list resources and control block
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_clean_list(UINT8 inst_idx, UINT8 sess_idx)
+{
+
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_DIRLIST *p_dir = &p_cb->dir;
+ /*tBTA_MSE_CO_FOLDER_ENTRY *p_entry = p_dir->p_entry; */
+ /* Clean up control block */
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_clean_list");
+#endif
+ bta_mse_set_ma_oper(inst_idx,sess_idx, BTA_MSE_OPER_NONE);
+ utl_freebuf((void**)&(p_dir->p_entry));
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_end_of_list
+**
+** Description Finishes up the end body of the get folder listing, and sends out the
+** OBX response
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** rsp_code - obex response code
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_end_of_list(UINT8 inst_idx, UINT8 sess_idx, UINT8 rsp_code)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 len = 0;
+ UINT8 *p, *p_start;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_end_of_list");
+#endif
+ /* Add the end of folder listing string if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* If listing has completed, add on end string (http) */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ if (p_cb->fl_param.max_list_cnt)
+ {
+ len = strlen(BTA_MSE_FOLDER_LISTING_END);
+ memcpy(&p_obx->p_start[p_obx->offset], BTA_MSE_FOLDER_LISTING_END, len);
+ p_obx->offset += len;
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE);
+ }
+ else
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("list_cnt=%d",p_cb->fl_param.list_cnt);
+#endif
+
+ /* send the folder list size header only*/
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ p = p_start;
+
+ *p++ = BTA_MA_APH_FOLDER_LST_SIZE;
+ *p++ = 2;
+ UINT16_TO_BE_STREAM(p, p_cb->fl_param.list_cnt);
+ if (p != p_start)
+ {
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+ }
+ /* Clean up control block */
+ bta_mse_clean_list(inst_idx, sess_idx);
+ }
+ else /* More listing data to be sent */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, FALSE);
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+ }
+ else /* An error occurred */
+ {
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_mse_clean_list(inst_idx, sess_idx);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_add_list_entry
+**
+** Description Adds an subfolder entry to the folder list object
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns UINT8 - OBX response code
+** OBX_RSP_PART_CONTENT if not finished yet.
+** OBX_RSP_CONTINUE [packet done]
+** Others send error response out
+**
+*******************************************************************************/
+UINT8 bta_mse_add_list_entry(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_DIRLIST *p_dir = &p_cb->dir;
+ tBTA_MSE_CO_FOLDER_ENTRY *p_entry = p_dir->p_entry;
+ char *p_buf;
+ UINT16 size;
+ UINT8 rsp_code = OBX_RSP_PART_CONTENT;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_add_list_entry");
+#endif
+ if ((p_buf = (char *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
+ {
+ p_buf[0] = '\0';
+
+ APPL_TRACE_DEBUG2("bta_mse_add_list_entry: attr:0x%02x, name:%s",
+ p_entry->mode, p_entry->p_name);
+
+ if (p_entry->mode & BTA_MA_A_DIR) /* only process Subdirectory ignore files */
+ {
+ /* ignore "." and ".." */
+ if (strcmp(p_entry->p_name, ".") && strcmp(p_entry->p_name, ".."))
+ {
+ p_cb->fl_param.list_cnt++;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("list_cnt=%d",p_cb->fl_param.list_cnt);
+#endif
+ if (p_cb->fl_param.max_list_cnt)
+ {
+ if (p_cb->fl_param.list_cnt <= p_cb->fl_param.max_list_cnt)
+ {
+ if (p_cb->fl_param.list_cnt > p_cb->fl_param.start_offset )
+ {
+ sprintf(p_buf, " <" BTA_MSE_FOLDER_ELEM " "
+ BTA_MSE_NAME_ATTR "=\"%s\"/>" BTA_MSE_XML_EOL,
+ p_entry->p_name);
+ }
+ }
+ } /* if max_list_cnt==0 only count the list size - but no body should be included*/
+ }
+ }/* ignore files i.e. non-folder items */
+
+ size = strlen(p_buf);
+ if (size <= p_obx->bytes_left)
+ {
+ if ( size > 0)
+ {
+ memcpy (&p_obx->p_start[p_obx->offset], p_buf, size);
+ p_obx->offset += size;
+ p_obx->bytes_left -= size;
+ }
+
+ if ((p_cb->fl_param.list_cnt < p_cb->fl_param.max_list_cnt) ||
+ (p_cb->fl_param.max_list_cnt == 0) )
+ {
+ /* Get the next directory entry */
+ p_cb->cout_active = TRUE;
+ bta_mse_co_get_folder_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ p_cb->p_workdir, FALSE, p_dir->p_entry,
+ BTA_MSE_CI_GET_FENTRY_EVT,
+ bta_mse_cb.app_id);
+ }
+ else
+ {
+ /* reach the max allowed */
+ rsp_code = OBX_RSP_OK;
+ }
+ }
+ else /* entry did not fit in current obx packet; try to add entry in next obx req */
+ {
+ p_cb->fl_param.list_cnt--;
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+
+ /* Done with temporary buffer */
+ GKI_freebuf(p_buf);
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ return(rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_getfolderlist
+**
+** Description Processes the retrieval of a folder listing.
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_getfolderlist(UINT8 inst_idx, UINT8 sess_idx, BOOLEAN new_req)
+{
+ tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_DIRLIST *p_dir = &p_cb->dir;
+ UINT16 temp_len;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+#if BTA_MSE_ENABLE_FS_CO == TRUE
+ BOOLEAN is_dir;
+#endif
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_getfolderlist");
+#endif
+
+#if BTA_MSE_ENABLE_FS_CO == TRUE
+ /* Make sure the Name is a directory and accessible */
+ if (((bta_fs_co_access(p_cb->p_workdir, BTA_FS_ACC_EXIST,
+ &is_dir, bta_mse_cb.app_id))!= BTA_FS_CO_OK)
+ || !is_dir)
+ rsp_code = OBX_RSP_NOT_FOUND;
+#endif
+ /* Build the listing */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /* p_cb->peer_mtu */ OBX_LRG_DATA_POOL_SIZE);
+ if (!(strcmp(p_cb->p_workdir, p_scb->p_rootpath)))
+ p_dir->is_root = TRUE;
+ else
+ p_dir->is_root = FALSE;
+
+ if (!p_dir->p_entry)
+ {
+ /* Allocate enough space for the structure and the folder name */
+ if ((p_dir->p_entry = (tBTA_MSE_CO_FOLDER_ENTRY *)
+ GKI_getbuf((UINT16)(sizeof(tBTA_MSE_CO_FOLDER_ENTRY) +
+ p_bta_mse_cfg->max_name_len + 1))) != NULL)
+ p_dir->p_entry->p_name = (char *)(p_dir->p_entry + 1);
+ }
+
+ if (p_dir->p_entry && p_obx->p_pkt)
+ {
+ if (p_cb->fl_param.max_list_cnt)
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+ }
+
+ /* Is this a new request or continuation? */
+ if (new_req)
+ {
+ APPL_TRACE_EVENT1("Folder List Directory: [%s]", p_cb->p_workdir);
+ p_cb->fl_param.list_cnt =0;
+
+ /* add body header if max_list_cnt is not 0
+ if max_list_cnt =0 then only report the actual number
+ accessible folders. Use FolderListingSize header only
+ */
+
+ if (p_cb->fl_param.max_list_cnt)
+ {
+ temp_len = strlen(BTA_MSE_FOLDER_LISTING_START);
+
+ /* Add the beginning label of http */
+ memcpy(p_obx->p_start, BTA_MSE_FOLDER_LISTING_START, temp_len);
+ p_obx->bytes_left -= (UINT16)(temp_len + strlen(BTA_MSE_FOLDER_LISTING_END));
+ p_obx->offset += temp_len;
+
+ /* Add the parent directory if not the root */
+ if (strcmp(p_cb->p_workdir, p_scb->p_rootpath))
+ {
+ APPL_TRACE_EVENT0("Add parent folder");
+
+ temp_len = strlen(BTA_MSE_PARENT_FOLDER);
+ memcpy(p_obx->p_start + p_obx->offset,
+ BTA_MSE_PARENT_FOLDER, temp_len);
+ p_obx->bytes_left -= temp_len;
+ p_obx->offset += temp_len;
+ }
+ }
+ p_cb->cout_active = TRUE;
+ bta_mse_co_get_folder_entry((tBTA_MA_SESS_HANDLE) p_cb->obx_handle,
+ p_cb->p_workdir, TRUE, p_dir->p_entry,
+ BTA_MSE_CI_GET_FENTRY_EVT,
+ bta_mse_cb.app_id);
+
+ /* List is not complete, so don't send the response yet */
+ rsp_code = OBX_RSP_PART_CONTENT;
+ }
+ else /* Add the entry previously retrieved */
+ rsp_code = bta_mse_add_list_entry(inst_idx, sess_idx);
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+
+ /* Response goes out if complete or error occurred */
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_mse_end_of_list(inst_idx, sess_idx,rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_chdir
+**
+** Description Changes the current path based on received setpath paramters
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_oper - (output) pointer to the MSE operation code
+**
+** Returns UINT8 - OBX response code
+** output *p_oper set to BTA_MSE_OPER_SETPATH if the
+** the resulting path is a valid path
+*******************************************************************************/
+UINT8 bta_mse_chdir(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_OPER *p_oper)
+{
+ tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ char *p_path = p_cb->sp.p_path;
+ char *p_name = p_cb->sp.p_name;
+ char *p_tmp;
+
+ char *p_workdir = p_cb->p_workdir;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+#if BTA_MSE_ENABLE_FS_CO == TRUE
+ BOOLEAN is_dir;
+#endif
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_chdir flag=%d name=%s",p_cb->sp.flags,p_cb->sp.p_name );
+#endif
+ *p_oper = BTA_MSE_OPER_NONE;
+ switch (p_cb->sp.flags)
+ {
+ case BTA_MA_DIR_NAV_ROOT_OR_DOWN_ONE_LVL:
+ p_path = p_cb->sp.p_path;
+ p_name = p_cb->sp.p_name;
+ rsp_code = OBX_RSP_OK;
+ if (*p_name == '\0')
+ {
+ /* backup to root */
+ if (strcmp(p_workdir, p_scb->p_rootpath))
+ {
+ BCM_STRNCPY_S(p_path, p_bta_fs_cfg->max_path_len+1, p_scb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ /* go back up to the root folder*/
+ *p_oper = BTA_MSE_OPER_SETPATH;
+ }
+ }
+ /* Make sure the new path is not too big */
+ /* +1 is for the separator */
+ else if ((strlen(p_workdir)+1+strlen(p_name)) <= p_bta_fs_cfg->max_path_len)
+ {
+ /* create a temporary path for creation attempt */
+ sprintf(p_path, "%s%c%s", p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+#if BTA_MSE_ENABLE_FS_CO == TRUE
+ if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST,
+ &is_dir, bta_mse_cb.app_id)) == BTA_FS_CO_OK) && is_dir)
+ {
+ /* go back down one level to the name folder*/
+ *p_oper = BTA_MSE_OPER_SETPATH;
+ }
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+#else
+ *p_oper = BTA_MSE_OPER_SETPATH;
+#endif
+ }
+ else
+ {
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ break;
+ case BTA_MA_DIR_NAV_UP_ONE_LVL:
+
+ if (strcmp(p_workdir, p_scb->p_rootpath))
+ {
+ /* Find the last occurrence of separator and replace with '\0' */
+ BCM_STRNCPY_S(p_path, p_bta_fs_cfg->max_path_len+1, p_workdir, p_bta_fs_cfg->max_path_len);
+ if ((p_tmp = strrchr(p_path, (int)p_bta_fs_cfg->path_separator)) != NULL)
+ {
+ *p_tmp = '\0';
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("path=[%s]",p_path );
+ APPL_TRACE_EVENT1("name=[%s]", p_name );
+#endif
+ /* now check we need to go down one level if name is not empty*/
+ if (*p_name !='\0')
+ {
+ if ((strlen(p_workdir)+1+strlen(p_name)) <= p_bta_fs_cfg->max_path_len)
+ {
+ sprintf(p_path, "%s%c%s", p_path,
+ p_bta_fs_cfg->path_separator, p_name);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("Up one level and then down one" );
+ APPL_TRACE_EVENT1("path=[%s]",p_path );
+#endif
+#if BTA_MSE_ENABLE_FS_CO == TRUE
+ if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST,
+ &is_dir, bta_mse_cb.app_id)) == BTA_FS_CO_OK) && is_dir)
+ {
+ /* go up one level and then go down one level to the name folder */
+ *p_oper = BTA_MSE_OPER_SETPATH;
+ }
+ else
+ {
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+#else
+ *p_oper = BTA_MSE_OPER_SETPATH;
+#endif
+ }
+ else
+ {
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+ else
+ {
+ /* just go up one level to the parent directory */
+ *p_oper = BTA_MSE_OPER_SETPATH;
+ }
+ }
+ else
+ {
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+ else
+ {
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+ break;
+ default:
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ break;
+ }
+
+ return(rsp_code);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_send_set_notif_reg
+**
+** Description Send a set notification registration event to application
+** so application can decide whether the request is allowed or not
+**
+** Parameters status - (output) pointer to the MSE operation code
+** inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns TRUE - request is sent FALSE - requestr is not sent due to
+** error in the request
+*******************************************************************************/
+BOOLEAN bta_mse_send_set_notif_reg(UINT8 status,
+ UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ tBTA_MSE cback_evt_data;
+ tBTA_MA_NOTIF_STATUS notif_sts = BTA_MA_NOTIF_OFF;
+ BOOLEAN send_status = TRUE;
+ UINT8 ccb_idx;
+
+ if (status & BTA_MA_NOTIF_STS_ON) notif_sts = BTA_MA_NOTIF_ON;
+
+ if (notif_sts == BTA_MA_NOTIF_OFF)
+ {
+ if (!bta_mse_find_bd_addr_match_mn_cb_index(p_cb->bd_addr, &ccb_idx))
+ {
+ send_status = FALSE;
+ }
+ }
+
+ if (send_status)
+ {
+ cback_evt_data.set_notif_reg.mas_session_id = p_cb->obx_handle;
+ cback_evt_data.set_notif_reg.mas_instance_id = p_scb->mas_inst_id;
+ cback_evt_data.set_notif_reg.notif_status = notif_sts;
+ bdcpy(cback_evt_data.set_notif_reg.bd_addr, p_cb->bd_addr);
+ bta_mse_cb.p_cback(BTA_MSE_SET_NOTIF_REG_EVT, (tBTA_MSE *) &cback_evt_data);
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_send_set_notif_reg send_status=%d",send_status );
+#endif
+
+
+ return send_status;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_proc_notif_reg_status
+**
+** Description Process the notification registration status to determine
+** whether a MN conenction should be opened or closed
+**
+** Parameters status - (output) pointer to the MSE operation code
+** inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_mse_proc_notif_reg_status(UINT8 status,
+ UINT8 inst_idx, UINT8 sess_idx )
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_MA_CB *p_scb = BTA_MSE_GET_INST_CB_PTR(inst_idx);
+ tBTA_MA_NOTIF_STATUS notif_sts = BTA_MA_NOTIF_OFF;
+ tBTA_MSE_MN_CB *p_ccb;
+ UINT8 ccb_idx;
+ tBTA_MSE_MN_ACT_TYPE mn_act_type = BTA_MSE_MN_ACT_TYPE_NONE;
+ tOBX_RSP_CODE rsp_code = OBX_RSP_OK;
+
+ tBTA_MSE cback_evt_data;
+ tBTA_MSE_MN_INT_OPEN *p_open_evt;
+ tBTA_MSE_MN_INT_CLOSE *p_close_evt;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_proc_notif_reg_status");
+#endif
+
+ if (status & BTA_MA_NOTIF_STS_ON) notif_sts = BTA_MA_NOTIF_ON;
+
+ switch (notif_sts)
+ {
+ case BTA_MA_NOTIF_ON:
+
+ if (!bta_mse_find_bd_addr_match_mn_cb_index(p_cb->bd_addr, &ccb_idx))
+ {
+ if (bta_mse_find_avail_mn_cb_idx(&ccb_idx))
+ mn_act_type = BTA_MSE_MN_ACT_TYPE_OPEN_CONN;
+ else
+ mn_act_type = BTA_MSE_MN_ACT_TYPE_OPEN_CONN_ERR;
+ }
+ else
+ {
+ /* it is connected already */
+ mn_act_type = BTA_MSE_MN_ACT_TYPE_OPEN_CONN_NONE;
+ }
+ break;
+
+ case BTA_MA_NOTIF_OFF:
+
+ if (!bta_mse_find_bd_addr_match_mn_cb_index(p_cb->bd_addr, &ccb_idx))
+ {
+ mn_act_type = BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_ERR;
+ break;
+ }
+
+ p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+ if ((p_ccb->state !=BTA_MSE_MN_W4_CONN_ST) &&
+ (p_ccb->state !=BTA_MSE_MN_CONN_ST))
+ {
+ /* MN is either idle or to be closed shortly so do nothing*/
+ mn_act_type = BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_NONE;
+ }
+ else
+ {
+ if (bta_mse_mn_is_ok_to_close_mn(p_cb->bd_addr, p_scb->mas_inst_id))
+ {
+ /* This is the last active MN session using this conncection*/
+ mn_act_type = BTA_MSE_MN_ACT_TYPE_CLOSE_CONN;
+ }
+ else
+ {
+ mn_act_type = BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_NONE;
+ }
+ }
+ break;
+ }
+
+ switch (mn_act_type)
+ {
+ case BTA_MSE_MN_ACT_TYPE_OPEN_CONN:
+
+ if ((p_open_evt = (tBTA_MSE_MN_INT_OPEN *) GKI_getbuf(sizeof(tBTA_MSE_MN_INT_OPEN))) != NULL)
+ {
+ bta_mse_mn_add_inst_id(ccb_idx, p_scb->mas_inst_id);
+ p_open_evt->hdr.event = BTA_MSE_MN_INT_OPEN_EVT;
+ p_open_evt->ccb_idx = ccb_idx;
+ p_open_evt->sec_mask = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ memcpy(p_open_evt->bd_addr, p_cb->bd_addr, sizeof(BD_ADDR));
+ bta_sys_sendmsg(p_open_evt);
+ }
+ else
+ {
+ rsp_code = OBX_RSP_FAILED;
+ }
+
+ break;
+
+ case BTA_MSE_MN_ACT_TYPE_CLOSE_CONN:
+
+ if ((p_close_evt = (tBTA_MSE_MN_INT_CLOSE *) GKI_getbuf(sizeof(tBTA_MSE_MN_INT_CLOSE))) != NULL)
+ {
+ bta_mse_mn_remove_inst_id(ccb_idx, p_scb->mas_inst_id);
+ p_close_evt->hdr.event = BTA_MSE_MN_INT_CLOSE_EVT;
+ p_close_evt->ccb_idx = ccb_idx;
+ bta_sys_sendmsg(p_close_evt);
+ }
+ else
+ {
+ rsp_code = OBX_RSP_FAILED;
+ }
+ break;
+
+ case BTA_MSE_MN_ACT_TYPE_OPEN_CONN_ERR:
+ rsp_code = OBX_RSP_FAILED;
+ break;
+
+ case BTA_MSE_MN_ACT_TYPE_OPEN_CONN_NONE:
+ bta_mse_mn_add_inst_id(ccb_idx, p_scb->mas_inst_id);
+ break;
+ case BTA_MSE_MN_ACT_TYPE_CLOSE_CONN_NONE:
+ bta_mse_mn_remove_inst_id(ccb_idx, p_scb->mas_inst_id);
+ break;
+ default:
+ break;
+ }
+
+ OBX_PutRsp(p_cb->obx_handle , rsp_code, NULL);
+ if (rsp_code == OBX_RSP_OK)
+ cback_evt_data.notif_reg.status = BTA_MA_STATUS_OK;
+ else
+ cback_evt_data.notif_reg.status = BTA_MA_STATUS_FAIL;
+ cback_evt_data.notif_reg.mas_session_id = p_cb->obx_handle;
+ cback_evt_data.notif_reg.mas_instance_id = p_scb->mas_inst_id;
+ cback_evt_data.notif_reg.notif_status = notif_sts;
+ bdcpy(cback_evt_data.notif_reg.bd_addr, p_cb->bd_addr);
+ bta_mse_clean_set_notif_reg(inst_idx,sess_idx);
+
+ bta_mse_cb.p_cback(BTA_MSE_NOTIF_REG_EVT, (tBTA_MSE *) &cback_evt_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_discard_data
+**
+** Description frees the data
+**
+** Parameters event - MSE event
+** p_data - Pointer to the MSE event data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_discard_data(UINT16 event, tBTA_MSE_DATA *p_data)
+{
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_discard_data");
+#endif
+
+ switch (event)
+ {
+ case BTA_MSE_MA_OBX_CONN_EVT:
+ case BTA_MSE_MA_OBX_DISC_EVT:
+ case BTA_MSE_MA_OBX_ABORT_EVT:
+ case BTA_MSE_MA_OBX_CLOSE_EVT:
+ case BTA_MSE_MA_OBX_PUT_EVT:
+ case BTA_MSE_MA_OBX_GET_EVT:
+ case BTA_MSE_MA_OBX_SETPATH_EVT:
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+ break;
+
+ default:
+ /*Nothing to free*/
+ break;
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_mse_find_mas_inst_id_match_cb_idx
+**
+** Description Finds the MAS instance control block index based on the specified
+** MAS instance ID
+**
+** Parameters mas_inst_id - MAS instance ID
+** p_idx - (output) pointer to the MA control block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+*******************************************************************************/
+BOOLEAN bta_mse_find_mas_inst_id_match_cb_idx(tBTA_MA_INST_ID mas_inst_id, UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (bta_mse_cb.scb[i].in_use)
+ {
+ if (bta_mse_cb.scb[i].mas_inst_id == mas_inst_id)
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("bta_mse_find_mas_inst_id_match_cb_idx found=%d, inst_id=%d inst_idx=%d",
+ found, mas_inst_id, i);
+#endif
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_find_bd_addr_match_sess_cb_idx
+**
+** Description Finds the Session control block index based on the specified
+** MAS instance control block index and BD address
+**
+** Parameters bd_addr - BD address
+** inst_idx - MA control block index
+** p_idx - (output) pointer to the MA server control block
+** index
+**
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+*******************************************************************************/
+BOOLEAN bta_mse_find_bd_addr_match_sess_cb_idx(BD_ADDR bd_addr, UINT8 inst_idx,
+ UINT8 *p_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb;
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_MSE_NUM_SESS ; i ++)
+ {
+ p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, i);
+ if ((p_cb->state == BTA_MSE_MA_CONN_ST) &&
+ !memcmp (p_cb->bd_addr, bd_addr, BD_ADDR_LEN))
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("bta_mse_find_bd_addr_match_sess_cb_idx found=%d, inst_idx=%d p_idx=%d",
+ found, inst_idx, i);
+#endif
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_find_handle_match_mas_inst_cb_idx
+**
+** Description Finds the MAS instance control block index based on the specified Obx handle
+**
+** Parameters obx_handle - Obex session handle
+** p_idx - (output) pointer to the MA server control block index
+**
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_handle_match_mas_inst_cb_idx(tOBX_HANDLE obx_handle, UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (bta_mse_cb.scb[i].in_use)
+ {
+ if (bta_mse_cb.scb[i].obx_handle == obx_handle)
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_find_handle_match_mas_inst_cb_idx found=%d idx=%d",found, i);
+#endif
+ return found;
+}
+/*******************************************************************************
+**
+** Function bta_mse_find_mas_sess_cb_idx
+**
+** Description Finds the MAS instance and session control block indexes
+** based on Obx handle
+**
+** Parameters obx_handle - Obex session handle
+** p_mas_inst_idx - (output) pointer to the MA server control
+** block index
+** p_mas_sess_idx - (output) pointer to the MA session control
+** block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_mas_sess_cb_idx(tOBX_HANDLE obx_handle,
+ UINT8 *p_mas_inst_idx, UINT8 *p_mas_sess_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i, j;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_find_mas_sess_cb_idx");
+#endif
+ for (i=0; i< BTA_MSE_NUM_INST; i++)
+ {
+ if (bta_mse_cb.scb[i].in_use)
+ {
+ for (j=0; j < BTA_MSE_NUM_SESS; j++ )
+ {
+ if ( (bta_mse_cb.scb[i].sess_cb[j].state != BTA_MSE_MA_LISTEN_ST) &&
+ (bta_mse_cb.scb[i].sess_cb[j].obx_handle == obx_handle) )
+ {
+ found = TRUE;
+ *p_mas_inst_idx = i;
+ *p_mas_sess_idx = j;
+ return found;
+ }
+ }
+ }
+ }
+
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_find_ma_cb_indexes
+**
+** Description Finds the MAS instance and session control block indexes
+** based on the received internal event
+**
+** Parameters p_msg - Pointer to MSE msg data
+** p_mas_inst_idx - (output) pointer to the MA server control
+** block index
+** p_mas_sess_idx - (output) pointer to the MA session control
+** block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_ma_cb_indexes(tBTA_MSE_DATA *p_msg,
+ UINT8 *p_inst_idx, UINT8 *p_sess_idx)
+{
+ BOOLEAN found = FALSE;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_find_ma_cb_indexes");
+#endif
+ switch (p_msg->hdr.event)
+ {
+ case BTA_MSE_MA_OBX_CONN_EVT:
+
+ if (bta_mse_find_handle_match_mas_inst_cb_idx( p_msg->obx_evt.param.conn.handle, p_inst_idx))
+ {
+ if (bta_mse_find_avail_mas_sess_cb_idx(&(bta_mse_cb.scb[*p_inst_idx]), p_sess_idx))
+ found = TRUE;
+ }
+ break;
+
+ case BTA_MSE_API_ACCESSRSP_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->api_access_rsp.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+
+ case BTA_MSE_API_UPD_IBX_RSP_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->api_upd_ibx_rsp.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+
+ case BTA_MSE_API_SET_NOTIF_REG_RSP_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->api_set_notif_reg_rsp.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+
+ case BTA_MSE_INT_CLOSE_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->int_close.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+
+ case BTA_MSE_CI_GET_FENTRY_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_get_fentry.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+ case BTA_MSE_CI_GET_ML_INFO_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_get_ml_info.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+ case BTA_MSE_CI_GET_ML_ENTRY_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_get_ml_entry.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+ case BTA_MSE_CI_GET_MSG_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_get_msg.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+
+ case BTA_MSE_CI_PUSH_MSG_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_push_msg.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+
+ case BTA_MSE_CI_DEL_MSG_EVT:
+
+ if (bta_mse_find_sess_id_match_ma_cb_indexes(p_msg->ci_del_msg.mas_session_id,
+ p_inst_idx,p_sess_idx))
+ found = TRUE;
+
+ break;
+
+ case BTA_MSE_MA_OBX_DISC_EVT:
+ case BTA_MSE_MA_OBX_ABORT_EVT:
+ case BTA_MSE_MA_OBX_CLOSE_EVT:
+ case BTA_MSE_MA_OBX_PUT_EVT:
+ case BTA_MSE_MA_OBX_GET_EVT:
+ case BTA_MSE_MA_OBX_SETPATH_EVT:
+
+ if (bta_mse_find_mas_sess_cb_idx( p_msg->obx_evt.handle, p_inst_idx, p_sess_idx))
+ found = TRUE;
+ break;
+ default:
+ break;
+
+ }
+
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_cleanup
+**
+** Description Free resources if unable to find MA control block indexes
+**
+** Parameters p_msg - Pointer to MSE msg data
+**
+** Returns none
+**
+*******************************************************************************/
+void bta_mse_ma_cleanup(tBTA_MSE_DATA *p_msg)
+{
+ tBTA_MSE_OBX_EVT *p_evt = &p_msg->obx_evt;
+ tBTA_MA_OBX_RSP *p_rsp = NULL;
+ UINT8 rsp_code = OBX_RSP_BAD_REQUEST;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_ma_cleanup");
+#endif
+ switch (p_msg->hdr.event)
+ {
+ case BTA_MSE_MA_OBX_CONN_EVT:
+ p_rsp = OBX_ConnectRsp;
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+ break;
+ case BTA_MSE_MA_OBX_DISC_EVT:
+ p_rsp = OBX_DisconnectRsp;
+ break;
+ case BTA_MSE_MA_OBX_ABORT_EVT:
+ p_rsp = OBX_AbortRsp;
+ break;
+ case BTA_MSE_MA_OBX_PUT_EVT:
+ p_rsp = OBX_PutRsp;
+ break;
+ case BTA_MSE_MA_OBX_GET_EVT:
+ p_rsp = OBX_GetRsp;
+ break;
+ case BTA_MSE_MA_OBX_SETPATH_EVT:
+ p_rsp = OBX_SetPathRsp;
+ break;
+ default:
+ break;
+ }
+
+ if (p_rsp)
+ {
+ (*p_rsp)(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_mse_is_a_duplicate_id
+**
+** Description Determine the MAS instance ID has been used or not by other MAS instance
+**
+** Parameters mas_inst_id - MAS instance ID
+**
+** Returns BOOLEAN - TRUE the MAS isntance is a duplicate ID
+** FALSE not a duplicate ID
+*******************************************************************************/
+BOOLEAN bta_mse_is_a_duplicate_id(tBTA_MA_INST_ID mas_inst_id)
+{
+ BOOLEAN is_duplicate=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (bta_mse_cb.scb[i].in_use &&
+ (bta_mse_cb.scb[i].mas_inst_id == mas_inst_id))
+ {
+ is_duplicate = TRUE;
+
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_is_a_duplicate_id inst_id=%d status=%d",
+ mas_inst_id, is_duplicate);
+#endif
+
+ return is_duplicate;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_find_avail_mas_inst_cb_idx
+**
+** Description Finds a not in used MAS instance control block index
+**
+** Parameters p_idx - (output) pointer to the MA server control
+** block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_avail_mas_inst_cb_idx(UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (!bta_mse_cb.scb[i].in_use)
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_find_avail_mas_inst_cb_idx found=%d inst_idx=%d",
+ found, i);
+#endif
+ return found;
+}
+/*******************************************************************************
+**
+** Function bta_mse_find_avail_mas_sess_cb_idx
+**
+** Description Finds a not in used MAS session control block index
+**
+** Parameters p_scb - Pointer to the MA control block
+** p_idx - (output) pointer to the MA session control
+** block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+*******************************************************************************/
+BOOLEAN bta_mse_find_avail_mas_sess_cb_idx(tBTA_MSE_MA_CB *p_scb, UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_MSE_NUM_SESS ; i ++)
+ {
+ if (p_scb->sess_cb[i].state == BTA_MSE_MA_LISTEN_ST)
+ {
+ if ((p_scb->sess_cb[i].p_workdir = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ found = TRUE;
+ *p_idx = i;
+ }
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_find_avail_mas_sess_cb_idx found=%d idx=%d", found, i);
+#endif
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_find_avail_mn_cb_idx
+**
+** Description Finds a not in use MN control block index
+**
+** Parameters p_idx - (output) pointer to the MN control block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_avail_mn_cb_idx(UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_find_avail_mn_cb_idx");
+#endif
+ for (i=0; i < BTA_MSE_NUM_MN ; i ++)
+ {
+ if (!bta_mse_cb.ccb[i].in_use)
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+ return found;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_mse_find_bd_addr_match_mn_cb_index
+**
+** Description Find the MN control block index based on the specified BD address
+**
+** Parameters p_bd_addr - Pointer to the BD address
+** p_idx - (output) pointer to the MN control block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+
+BOOLEAN bta_mse_find_bd_addr_match_mn_cb_index(BD_ADDR p_bd_addr, UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_MSE_NUM_MN ; i ++)
+ {
+ if ((bta_mse_cb.ccb[i].in_use) &&
+ (!memcmp (bta_mse_cb.ccb[i].bd_addr, p_bd_addr, BD_ADDR_LEN)))
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_find_bd_addr_match_mn_cb_index found=%d index=%d", found, i);
+#endif
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_find_bd_addr_match_mn_cb_index
+**
+** Description Find the MN control block index based on the specified obx handle
+**
+** Parameters obx_hdl - Obex session handle
+** p_idx - (output) pointer to the MN control block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+
+BOOLEAN bta_mse_find_obx_hdl_match_mn_cb_index(tOBX_HANDLE obx_hdl, UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_find_obx_hdl_match_mn_cb_index");
+#endif
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if ((bta_mse_cb.ccb[i].in_use) &&
+ (bta_mse_cb.ccb[i].obx_handle == obx_hdl))
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_find_sess_id_match_ma_cb_indexes
+**
+** Description Finds the MAS instance and session control block indexes
+** based on the specified MAS session ID
+**
+** Parameters mas_session_id - MAS instance ID
+** p_inst_idx - (output) pointer to the MA server control
+** block index
+** p_sess_idx - (output) pointer to the MA session control
+** block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_sess_id_match_ma_cb_indexes(tBTA_MA_SESS_HANDLE mas_session_id,
+ UINT8 *p_inst_idx, UINT8 *p_sess_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i,j;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_find_sess_id_match_ma_cb_indexes");
+#endif
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ for (j=0; j<BTA_MSE_NUM_SESS; j++ )
+ {
+ if ((bta_mse_cb.scb[i].in_use) &&
+ (bta_mse_cb.scb[i].sess_cb[j].obx_handle == (tOBX_HANDLE) mas_session_id ))
+ {
+ found = TRUE;
+ *p_inst_idx = i;
+ *p_sess_idx = j;
+ return found;
+ }
+ }
+ }
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_find_sess_id_match_mn_cb_index
+**
+** Description Finds the MN control block index
+** based on the specified MAS session ID
+**
+** Parameters mas_session_id - MAS instance ID
+** p_idx - (output) pointer to the MN control
+** block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_sess_id_match_mn_cb_index(tBTA_MA_SESS_HANDLE mas_session_id,
+ UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+
+ UINT8 i,j;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_find_sess_id_match_mn_cb_index");
+#endif
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ for (j=0; j<BTA_MSE_NUM_SESS; j++ )
+ {
+ if ((bta_mse_cb.scb[i].in_use) &&
+ (bta_mse_cb.scb[i].sess_cb[j].obx_handle == (tOBX_HANDLE) mas_session_id ))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found) break;
+ }
+
+ /* found session index now need to match BD address*/
+ if (found)
+ {
+ found = FALSE;
+ if ( bta_mse_find_bd_addr_match_mn_cb_index(bta_mse_cb.scb[i].sess_cb[j].bd_addr, p_idx))
+ {
+ found = TRUE;
+ }
+ }
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_find_mn_cb_index
+**
+** Description Finds the MN control block index
+** based on the specified event
+**
+** Parameters p_msg - Pointer to MSE msg data
+** p_ccb_idx - (output) pointer to the MN control block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_mn_cb_index(tBTA_MSE_DATA *p_msg, UINT8 *p_ccb_idx)
+{
+ BOOLEAN found = TRUE;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_find_mn_cb_index");
+#endif
+ switch (p_msg->hdr.event)
+ {
+ case BTA_MSE_MN_INT_OPEN_EVT:
+ *p_ccb_idx= p_msg->mn_int_open.ccb_idx;
+ break;
+
+ case BTA_MSE_MN_INT_CLOSE_EVT:
+ *p_ccb_idx= p_msg->mn_int_close.ccb_idx;
+ break;
+
+ case BTA_MSE_MN_OBX_CONN_RSP_EVT:
+
+ if (!bta_mse_find_bd_addr_match_mn_cb_index(
+ p_msg->obx_evt.param.conn.peer_addr,
+ p_ccb_idx))
+ {
+ found = FALSE;
+ }
+ break;
+
+ case BTA_MSE_MN_OBX_TOUT_EVT:
+ case BTA_MSE_MN_OBX_CLOSE_EVT:
+ case BTA_MSE_MN_OBX_PUT_RSP_EVT:
+ if (!bta_mse_find_obx_hdl_match_mn_cb_index(
+ p_msg->obx_evt.handle,
+ p_ccb_idx))
+ {
+ found = FALSE;
+ }
+
+ break;
+
+ case BTA_MSE_MN_SDP_OK_EVT:
+
+ *p_ccb_idx = p_msg->mn_sdp_ok.ccb_idx;
+ break;
+
+ case BTA_MSE_MN_SDP_FAIL_EVT:
+
+ *p_ccb_idx = p_msg->mn_sdp_fail.ccb_idx;
+ break;
+
+ default:
+ found = FALSE;
+ break;
+ }
+
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_cleanup
+**
+** Description Free resources if unable to find MN control block index
+**
+** Parameters p_msg - Pointer to MSE msg data
+**
+** Returns none
+**
+*******************************************************************************/
+void bta_mse_mn_cleanup(tBTA_MSE_DATA *p_msg)
+{
+ tBTA_MSE_OBX_EVT *p_evt = &p_msg->obx_evt;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_mn_cleanup");
+#endif
+ switch (p_msg->hdr.event)
+ {
+ case BTA_MSE_MN_OBX_CONN_RSP_EVT:
+ case BTA_MSE_MN_OBX_PUT_RSP_EVT:
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+ break;
+
+ default:
+ break;
+ }
+}
+/*******************************************************************************
+**
+** Function bta_mse_build_map_event_rpt_obj
+**
+** Description Create a MAP-Event-Report object in the
+** specified buffer.
+**
+** Parameters notif_type - Notification type
+** handle (input only) - handle of the message that the "type"
+** indication refers to. Ignored when the event "type" is
+** "MemoryFull" or "MemoryAvailable".
+** p_folder - name of the folder in which the corresponding
+** message has been filed by the MSE. NULL when the event
+** "type" is "MemoryFull" or "MemoryAvailable".
+** p_old_folder - Used only in case of a message shift to
+** indicate the folder on the MSE from which the message
+** has been shifted out.
+** msg_typ - Gives the type of the message. Ignored when the
+** event "type" is "MemoryFull" or "MemoryAvailable".
+** p_len - Pointer to value containing the size of
+** the buffer (p_buffer). Receives the output size of
+** filled XML object.
+** p_buffer - Pointer to buffer to receive the XML object.
+**
+** Returns BTA_MA_STATUS_FAIL if buffer was not large enough, otherwise
+** returns BTA_MA_STATUS_OK.
+**
+*******************************************************************************/
+tBTA_MA_STATUS bta_mse_build_map_event_rpt_obj(tBTA_MSE_NOTIF_TYPE notif_type,
+ tBTA_MA_MSG_HANDLE handle,
+ char * p_folder,
+ char * p_old_folder,
+ tBTA_MA_MSG_TYPE msg_typ,
+ UINT16 * p_len,
+ UINT8 * p_buffer)
+{
+ tBTA_MA_STREAM strm;
+
+ memset(p_buffer, 0, *p_len);
+ BTA_MaInitMemStream(&strm, p_buffer, *p_len);
+
+ /* stream event attribute and event type */
+ bta_ma_stream_str(&strm, "<MAP-event-report version=\"1.0\">\n"
+ "<event type = \"");
+ bta_ma_stream_str(&strm, bta_ma_evt_typ_to_string(notif_type));
+
+ /* Some things are not used for "MemoryFull" and "MemoryAvailable" */
+ if ( (BTA_MSE_NOTIF_TYPE_MEMORY_FULL != notif_type)
+ && (BTA_MSE_NOTIF_TYPE_MEMORY_AVAILABLE != notif_type) )
+ {
+ /* stream handle label and value */
+ bta_ma_stream_str(&strm, "\" handle = \"");
+ bta_ma_stream_handle(&strm, handle);
+
+ if (p_folder && (*p_folder !='\0'))
+ {
+ /* stream folder */
+ bta_ma_stream_str(&strm, "\" folder = \"");
+ bta_ma_stream_str(&strm, p_folder);
+ }
+
+ /* stream old_folder if it is a "MessageShift" */
+ if ( (BTA_MSE_NOTIF_TYPE_MESSAGE_SHIFT == notif_type) &&
+ p_old_folder && (*p_old_folder !='\0'))
+ {
+ /* stream folder */
+ bta_ma_stream_str(&strm, "\" old_folder = \"");
+ bta_ma_stream_str(&strm, p_old_folder);
+ }
+
+ /* stream message type */
+ bta_ma_stream_str(&strm, "\" msg_type = \"");
+ bta_ma_stream_str(&strm, bta_ma_msg_typ_to_string(msg_typ));
+ }
+
+ /* we are done with this evnet */
+ bta_ma_stream_str(&strm, "\" />\n</MAP-event-report>");
+
+ /* set the output length (i.e. amount of buffer that got used) */
+ *p_len = bta_ma_stream_used_size(&strm);
+
+ /* return status based on the stream status */
+ return(bta_ma_stream_ok(&strm)
+ ? BTA_MA_STATUS_OK
+ : BTA_MA_STATUS_FAIL);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_build_msg_listing_obj
+**
+** Description Build the message listing object in the specified buffer
+**
+** Parameters p_entry - Pointer to the message listing entry
+** p_size - input: pointer to the available buffer size
+** output: pointer to the filled buffer size
+** p_buf - pointer to the buffer for building the msg listing
+** object
+**
+** Returns status - BTA_MA_STATUS_OK - build the object successfully
+** BTA_MA_STATUS_FAIL - failed to build the object
+**
+*******************************************************************************/
+tBTA_MA_STATUS bta_mse_build_msg_listing_obj(tBTA_MSE_CO_MSG_LIST_ENTRY *p_entry,
+ UINT16 *p_size, char *p_buf )
+{
+ tBTA_MA_STREAM strm;
+
+ memset(p_buf, 0, *p_size);
+ BTA_MaInitMemStream(&strm, (UINT8 *)p_buf, *p_size);
+
+ /* stream msg element */
+ bta_ma_stream_str(&strm, "<msg ");
+ /* stream msg attributes */
+ bta_ma_stream_str(&strm, "handle = \"");
+ bta_ma_stream_handle(&strm, p_entry->msg_handle);
+
+ if (p_entry->parameter_mask &BTA_MA_ML_MASK_SUBJECT)
+ {
+ bta_ma_stream_str(&strm, "\" subject = \"");
+ bta_ma_stream_str(&strm, p_entry->subject);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_DATETIME)
+ {
+ bta_ma_stream_str(&strm, "\" datetime = \"");
+ bta_ma_stream_str(&strm, p_entry->date_time);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_SENDER_NAME)
+ {
+ bta_ma_stream_str(&strm, "\" sender_name = \"");
+ bta_ma_stream_str(&strm, p_entry->sender_name);
+ }
+
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_SENDER_ADDRESSING)
+ {
+ bta_ma_stream_str(&strm, "\" sender_addressing = \"");
+ bta_ma_stream_str(&strm, p_entry->sender_addressing);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_REPLYTO_ADDRESSING)
+ {
+ bta_ma_stream_str(&strm, "\" replyto_addressing = \"");
+ bta_ma_stream_str(&strm, p_entry->replyto_addressing);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_RECIPIENT_NAME)
+ {
+ bta_ma_stream_str(&strm, "\" recipient_name = \"");
+ bta_ma_stream_str(&strm, p_entry->recipient_name);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_RECIPIENT_ADDRESSING)
+ {
+ bta_ma_stream_str(&strm, "\" recipient_addressing = \"");
+ bta_ma_stream_str(&strm, p_entry->recipient_addressing);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_TYPE)
+ {
+ bta_ma_stream_str(&strm, "\" type = \"");
+ if (!bta_ma_stream_str(&strm, bta_ma_msg_typ_to_string(p_entry->type)))
+ {
+ return BTA_MA_STATUS_FAIL;
+ }
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_SIZE)
+ {
+ bta_ma_stream_str(&strm, "\" size = \"");
+ bta_ma_stream_value(&strm, p_entry->org_msg_size);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_TEXT)
+ {
+ bta_ma_stream_str(&strm, "\" text = \"");
+ bta_ma_stream_boolean_yes_no(&strm, p_entry->text);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_RECEPTION_STATUS)
+ {
+ bta_ma_stream_str(&strm, "\" reception_status = \"");
+ if (!bta_ma_stream_str(&strm,
+ bta_ma_rcv_status_to_string(p_entry->reception_status)))
+ {
+ return BTA_MA_STATUS_FAIL;
+ }
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_ATTACHMENT_SIZE)
+ {
+ bta_ma_stream_str(&strm, "\" attachment_size = \"");
+ bta_ma_stream_value(&strm, p_entry->attachment_size);
+ }
+
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_PRIORITY)
+ {
+ bta_ma_stream_str(&strm, "\" priority = \"");
+ bta_ma_stream_boolean_yes_no(&strm, p_entry->high_priority);
+ }
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_READ)
+ {
+ bta_ma_stream_str(&strm, "\" read = \"");
+ bta_ma_stream_boolean_yes_no(&strm, p_entry->read);
+ }
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_SENT)
+ {
+ bta_ma_stream_str(&strm, "\" sent = \"");
+ bta_ma_stream_boolean_yes_no(&strm, p_entry->sent);
+ }
+ if (p_entry->parameter_mask & BTA_MA_ML_MASK_PROTECTED)
+ {
+ bta_ma_stream_str(&strm, "\" protected = \"");
+ bta_ma_stream_boolean_yes_no(&strm, p_entry->is_protected);
+ }
+
+ /* stream msg element end tag*/
+ bta_ma_stream_str(&strm, "\"/> ");
+
+ /* set the output length (i.e. amount of buffer that got used) */
+ *p_size = bta_ma_stream_used_size(&strm);
+
+ /* return status based on the stream status */
+ return(bta_ma_stream_ok(&strm)
+ ? BTA_MA_STATUS_OK
+ : BTA_MA_STATUS_FAIL);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_start_timer
+**
+** Description Start a wait for obx response timer
+**
+** Parameters ccb_inx - MN control block index
+** timer_id - indicating this timer is for which operation
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_mse_mn_start_timer(UINT8 ccb_idx, UINT8 timer_id)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ UINT16 event_id;
+ p_cb->rsp_timer.param = (UINT32) (ccb_idx+1);
+ event_id = (UINT16) BTA_MSE_MN_RSP0_TOUT_EVT + ccb_idx;
+ bta_sys_start_timer(&p_cb->rsp_timer, event_id,
+ p_bta_mse_cfg->obx_rsp_tout);
+
+ p_cb->timer_oper = timer_id;
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_start_stop_timer
+**
+** Description Stop a wait for obx response timer
+**
+** Parameters ccb_inx - MN control block index
+** timer_id - indicating this timer is for which operation
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_mse_mn_stop_timer(UINT8 ccb_idx, UINT8 timer_id)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+ if ((p_cb->timer_oper == timer_id) || (timer_id == BTA_MSE_TIMER_OP_ALL))
+ {
+ p_cb->rsp_timer.param = 0;
+ bta_sys_stop_timer(&p_cb->rsp_timer );
+ p_cb->timer_oper = BTA_MSE_TIMER_OP_NONE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_add_inst_id
+**
+** Description Add mas_inst_id to the MN notif_reg data base
+**
+** Parameters ccb_inx - MN control block index
+** mas_inst_id - MAS instance ID
+**
+** Returns BOOLEAN - TRUE OK
+** FALSE not OK
+**
+*******************************************************************************/
+BOOLEAN bta_mse_mn_add_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id)
+{
+ BOOLEAN found=FALSE;
+ BOOLEAN add_status=FALSE;
+ UINT8 i;
+ tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_mn_add_inst_id ccb_idx=%d mas_inst_id=%d",
+ ccb_idx, mas_inst_id);
+#endif
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (p_ccb->notif_reg[i].status &&
+ (p_ccb->notif_reg[i].mas_inst_id == mas_inst_id))
+ {
+ found = TRUE;
+ add_status = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (!p_ccb->notif_reg[i].status)
+ {
+ /* find an available entry to add */
+ p_ccb->notif_reg[i].mas_inst_id = mas_inst_id;
+ p_ccb->notif_reg[i].status = TRUE;
+ add_status = TRUE;
+ break;
+ }
+ }
+ }
+
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("add_status=%d", add_status);
+#endif
+
+ return add_status;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_remove_inst_id
+**
+** Description Remove mas_inst_id from the MN notif_reg data base
+**
+** Parameters ccb_inx - MN control block index
+** mas_inst_id - MAS instance ID
+**
+** Returns BOOLEAN - TRUE OK
+** FALSE not OK
+**
+*******************************************************************************/
+BOOLEAN bta_mse_mn_remove_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id)
+{
+ BOOLEAN remove_status=FALSE;
+ UINT8 i;
+ tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_mn_remove_inst_id ccb_idx=%d mas_inst_id=%d",
+ ccb_idx, mas_inst_id);
+#endif
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (p_ccb->notif_reg[i].status &&
+ (p_ccb->notif_reg[i].mas_inst_id == mas_inst_id))
+ {
+ p_ccb->notif_reg[i].status = FALSE;
+ p_ccb->notif_reg[i].mas_inst_id =(tBTA_MA_INST_ID )0;
+
+ remove_status = TRUE;
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("remove_status=%d", remove_status);
+#endif
+
+ return remove_status;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_remove_all_inst_ids
+**
+** Description Remove all mas_inst_ids from the MN notif_reg data base
+**
+** Parameters ccb_inx - MN control block index
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_mse_mn_remove_all_inst_ids(UINT8 ccb_idx)
+{
+ UINT8 i;
+ tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT1("bta_mse_mn_remove_all_inst_ids ccb_idx=%d ",
+ ccb_idx);
+#endif
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (p_ccb->notif_reg[i].status)
+ {
+ p_ccb->notif_reg[i].status = FALSE;
+ p_ccb->notif_reg[i].mas_inst_id =(tBTA_MA_INST_ID) 0;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_find_num_of_act_inst_id
+**
+** Description fin the number of Mas Instance IDs with registration status on
+**
+** Parameters ccb_inx - MN control block index
+**
+** Returns UINT8 - Number of active Mas Instance ID
+**
+*******************************************************************************/
+UINT8 bta_mse_mn_find_num_of_act_inst_id(UINT8 ccb_idx)
+{
+ UINT8 i,cnt;
+ tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);;
+
+ cnt =0;
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (p_ccb->notif_reg[i].status) cnt++;
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_mn_find_num_of_act_inst_id ccb_idx=%d cnt=%d",
+ ccb_idx, cnt);
+#endif
+
+ return cnt;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_is_inst_id_exist
+**
+** Description Check whether the specified mas_inst_id is in the
+** MN notif_reg data base
+**
+** Parameters ccb_inx - MN control block index
+** mas_inst_id - MAS instance ID
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+**
+*******************************************************************************/
+BOOLEAN bta_mse_mn_is_inst_id_exist(UINT8 ccb_idx, tBTA_MA_INST_ID mas_inst_id )
+{
+ BOOLEAN found = FALSE;
+ UINT8 i;
+ tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);;
+
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (p_ccb->notif_reg[i].status &&
+ (p_ccb->notif_reg[i].mas_inst_id == mas_inst_id))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("bta_mse_mn_is_inst_id_exist ccb_idx=%d mas_inst_id=%d found=%d",
+ ccb_idx, mas_inst_id, found);
+#endif
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_is_ok_to_close_mn
+**
+** Description Determine is ok to close MN connection
+**
+** Parameters bd_addr - BD address
+** mas_inst_id - MAS instance ID
+**
+** Returns BOOLEAN - TRUE OK
+** FALSE not OK
+**
+*******************************************************************************/
+BOOLEAN bta_mse_mn_is_ok_to_close_mn(BD_ADDR bd_addr, tBTA_MA_INST_ID mas_inst_id )
+{
+ UINT8 ccb_idx;
+ BOOLEAN ok_status= FALSE;
+
+
+ if (bta_mse_find_bd_addr_match_mn_cb_index(bd_addr, &ccb_idx) &&
+ (bta_mse_mn_find_num_of_act_inst_id(ccb_idx) == 1) &&
+ (bta_mse_mn_is_inst_id_exist(ccb_idx, mas_inst_id)))
+ {
+ ok_status = TRUE;
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_mn_is_ok_to_close_mn mas_inst_id=%d ok_status=%d",
+ mas_inst_id, ok_status);
+#endif
+
+ return ok_status;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_get_first_inst_id
+**
+** Description Get the first active mas_inst_id from the MN notif_reg data base
+**
+** Parameters ccb_inx - MN control block index
+** mas_inst_id - MAS instance ID
+**
+** Returns BOOLEAN - TRUE OK
+** FALSE not OK
+**
+*******************************************************************************/
+BOOLEAN bta_mse_mn_get_first_inst_id(UINT8 ccb_idx, tBTA_MA_INST_ID *p_mas_inst_id)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+ tBTA_MSE_MN_CB *p_ccb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+
+ for (i=0; i < BTA_MSE_NUM_INST ; i ++)
+ {
+ if (p_ccb->notif_reg[i].status )
+ {
+ *p_mas_inst_id = p_ccb->notif_reg[i].mas_inst_id;
+
+ found = TRUE;
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT3("bta_mse_mn_get_inst_id ccb_idx=%d found status =%d mas_inst_id=%d",
+ ccb_idx, found, *p_mas_inst_id);
+#endif
+
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_send_abort_req
+**
+** Description Send an abort request.
+**
+** Parameters ccb_inx - MN control block index
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_send_abort_req(UINT8 ccb_idx)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+
+ if (BTA_MSE_MN_ABORT_REQ_NOT_SENT == p_cb->aborting)
+ {
+ bta_mse_mn_start_timer(ccb_idx, BTA_MSE_TIMER_OP_ABORT);
+ OBX_AbortReq(p_cb->obx_handle, (BT_HDR *)NULL);
+ p_cb->aborting = BTA_MSE_MN_ABORT_REQ_SENT;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_cont_send_notif
+**
+** Description Continues the send notification operation. Builds a new OBX packet
+**
+** Parameters ccb_idx - MN control block index
+** first_pkt - first obex packet indicator
+**
+** Returns tBTA_MA_STATUS : BTA_MA_STATUS_OK if msg notification sent is ok
+** otherwise BTA_MA_STATUS_FAIL
+*******************************************************************************/
+tBTA_MA_STATUS bta_mse_mn_cont_send_notif(UINT8 ccb_idx, BOOLEAN first_pkt)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_MSE_MN_MSG_NOTIF *p_msg_notif = &p_cb->msg_notif;
+ tOBX_TRIPLET app_param[1];
+ UINT16 body_len;
+ BOOLEAN final_pkt = FALSE;
+ tBTA_MA_STATUS status = BTA_MA_STATUS_OK;
+
+ /* Do not start another request if currently aborting */
+ if (p_cb->aborting)
+ {
+ bta_mse_mn_send_abort_req(ccb_idx);
+ return status;
+ }
+
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, p_cb->peer_mtu)) != NULL)
+ {
+ if (first_pkt)
+ {
+ OBX_AddTypeHdr(p_obx->p_pkt, BTA_MA_HDR_TYPE_EVENT_RPT);
+
+ app_param[0].tag = BTA_MA_NAS_INST_ID_TAG_ID;
+ app_param[0].len = BTA_MA_NAS_INST_ID_LEN;
+ app_param[0].p_array = &(p_msg_notif->mas_instance_id);
+ OBX_AddAppParamHdr(p_obx->p_pkt, app_param, 1);
+ }
+ else
+ {
+ p_obx->offset =
+ p_obx->bytes_left = 0; /* 0 -length available */
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ body_len = p_obx->bytes_left;
+ final_pkt = ( (p_msg_notif->buffer_len - p_msg_notif->bytes_sent) < body_len) ?
+ TRUE : FALSE ;
+ if (final_pkt) body_len = (p_msg_notif->buffer_len - p_msg_notif->bytes_sent);
+
+ memcpy(&p_obx->p_start[p_obx->offset],
+ &(p_msg_notif->p_buffer[p_msg_notif->bytes_sent]), body_len);
+ p_msg_notif->bytes_sent += body_len;
+ p_obx->offset += body_len;
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE);
+ }
+
+ OBX_PutReq(p_cb->obx_handle, final_pkt , p_obx->p_pkt);
+ p_obx->p_pkt = NULL;
+ p_cb->req_pending = TRUE;
+ bta_mse_set_mn_oper(ccb_idx, BTA_MSE_MN_OP_PUT_EVT_RPT);
+ p_msg_notif->final_pkt = final_pkt;
+ p_msg_notif->pkt_cnt++;
+ }
+ else
+ {
+ status = BTA_MA_STATUS_FAIL;
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT4("bta_mse_mn_cont_send_notif ccb_idx=%d first_pkt=%d send_status=%d final=%d",
+ ccb_idx, first_pkt, status, final_pkt);
+#endif
+
+ return status;
+}
+/*******************************************************************************
+**
+** Function bta_mse_mn_send_notif_evt
+**
+** Description Issue a send notification event
+**
+** Parameters mas_instance_id - MAS instance ID
+** status - MS sttaus
+** bd_addr - BD address
+**
+**
+** Returns UINT8 OBX response code
+**
+*******************************************************************************/
+void bta_mse_mn_send_notif_evt(tBTA_MA_INST_ID mas_instance_id, tBTA_MA_STATUS status,
+ BD_ADDR bd_addr )
+{
+ tBTA_MSE param;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_mn_send_notif_evt mas_instance_id=%d status=%d",
+ mas_instance_id,
+ status);
+#endif
+
+ param.send_notif.mas_instance_id = mas_instance_id;
+ param.send_notif.status = status;
+ bdcpy(param.send_notif.bd_addr, bd_addr);
+ bta_mse_cb.p_cback(BTA_MSE_SEND_NOTIF_EVT, &param);
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_mn_clean_send_notif
+**
+** Description Clean up send notif resources and cotrol block
+**
+** Parameters ccb_idx - MN control block index
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_mn_clean_send_notif(UINT8 ccb_idx)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("bta_mse_mn_clean_send_notif");
+#endif
+
+ utl_freebuf((void**)&(p_cb->msg_notif.p_buffer));
+ bta_mse_set_mn_oper(ccb_idx, BTA_MSE_MN_OP_NONE);
+ p_cb->req_pending = FALSE;
+ p_cb->aborting = BTA_MSE_MN_ABORT_NONE;
+ memset(&(p_cb->msg_notif), 0, sizeof(tBTA_MSE_MN_MSG_NOTIF));
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_fl_read_app_params
+**
+** Description Read application parameters for the get folder list requst
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_pkt - Pointer to the obex packet
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_mse_ma_fl_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt)
+
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 *p_param;
+ UINT16 len;
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_MAX_LIST_COUNT, &len);
+
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->fl_param.max_list_cnt, p_param);
+ }
+ else
+ p_cb->fl_param.max_list_cnt = BTA_MA_DEFAULT_MAX_LIST_CNT;
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_START_STOFF, &len);
+
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->fl_param.start_offset, p_param);
+ }
+ else
+ p_cb->fl_param.start_offset = 0;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_ml_read_app_params
+**
+** Description Read application parameters for the get message list requst
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_pkt - Pointer to the obex packet
+**
+** Returns void
+**
+*******************************************************************************/
+
+void bta_mse_ma_ml_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt)
+
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 *p_param;
+ UINT16 len;
+
+ memset(&(p_cb->ml_param.filter), 0x00, sizeof(tBTA_MA_MSG_LIST_FILTER_PARAM));
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_MAX_LIST_COUNT, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->ml_param.filter.max_list_cnt, p_param);
+ }
+ else
+ {
+ p_cb->ml_param.filter.max_list_cnt = BTA_MA_DEFAULT_MAX_LIST_CNT;
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_START_STOFF, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->ml_param.filter.list_start_offset, p_param);
+ }
+ else
+ {
+ p_cb->ml_param.filter.list_start_offset = 0;
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_SUBJ_LEN, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT8(p_cb->ml_param.filter.subject_length, p_param);
+ }
+ else
+ {
+ p_cb->ml_param.filter.subject_length = 0xff;
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_PARAM_MASK, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT32(p_cb->ml_param.filter.parameter_mask, p_param);
+ }
+ else
+ {
+ p_cb->ml_param.filter.parameter_mask = 0;
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_MSG_TYPE, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT8(p_cb->ml_param.filter.msg_mask, p_param);
+ }
+ else
+ {
+ p_cb->ml_param.filter.msg_mask = 0;
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_PRD_BEGIN, &len);
+
+ if (p_param)
+ {
+ p_cb->ml_param.filter.period_begin[BTA_MA_LTIME_LEN]='\0';
+ if (len < BTA_MA_LTIME_LEN)
+ {
+ p_cb->ml_param.filter.period_begin[0] = '\0';
+ }
+ else
+ {
+ BCM_STRNCPY_S((char *)p_cb->ml_param.filter.period_begin, sizeof(p_cb->ml_param.filter.period_begin),
+ (const char *)p_param, BTA_MA_LTIME_LEN);
+ }
+ }
+ else
+ {
+ p_cb->ml_param.filter.period_begin[0] = '\0';
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_PRD_END, &len);
+ if (p_param)
+ {
+ p_cb->ml_param.filter.period_end[BTA_MA_LTIME_LEN] = '\0';
+ if (len < BTA_MA_LTIME_LEN)
+ {
+ p_cb->ml_param.filter.period_end[0] = '\0';
+ }
+ else
+ {
+ BCM_STRNCPY_S((char *)p_cb->ml_param.filter.period_end, sizeof(p_cb->ml_param.filter.period_end),
+ (const char *)p_param, BTA_MA_LTIME_LEN);
+ }
+ }
+ else
+ {
+ p_cb->ml_param.filter.period_end[0] = '\0';
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_READ_STS, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT8(p_cb->ml_param.filter.read_status, p_param);
+ }
+ else
+ {
+ p_cb->ml_param.filter.read_status = 0;
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_RECEIP, &len);
+ p_cb->ml_param.filter.recipient[0] = '\0';
+ if (p_param && len)
+ {
+ if (len >= BTA_MA_MAX_FILTER_TEXT_SIZE)
+ {
+ p_cb->ml_param.filter.recipient[BTA_MA_MAX_FILTER_TEXT_SIZE] = '\0';
+ len = BTA_MA_MAX_FILTER_TEXT_SIZE;
+ }
+ BCM_STRNCPY_S((char *)p_cb->ml_param.filter.recipient, sizeof(p_cb->ml_param.filter.recipient),
+ (const char *)p_param, len);
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_ORIGIN, &len);
+ p_cb->ml_param.filter.originator[0] = '\0';
+ if (p_param && len)
+ {
+ if (len >= BTA_MA_MAX_FILTER_TEXT_SIZE)
+ {
+ p_cb->ml_param.filter.originator[BTA_MA_MAX_FILTER_TEXT_SIZE] = '\0';
+ len = BTA_MA_MAX_FILTER_TEXT_SIZE;
+ }
+ BCM_STRNCPY_S((char *)p_cb->ml_param.filter.originator, sizeof(p_cb->ml_param.filter.originator),
+ (const char *)p_param, len);
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FILTER_PRIORITY, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT8(p_cb->ml_param.filter.pri_status, p_param);
+ }
+ else
+ {
+ p_cb->ml_param.filter.pri_status = 0;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_ma_msg_read_app_params
+**
+** Description Read application parameters for the get message list requst
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_pkt - Pointer to the obex packet
+**
+** Returns BOOLEAN TRUE - operation is successful
+**
+*******************************************************************************/
+
+BOOLEAN bta_mse_ma_msg_read_app_params(UINT8 inst_idx, UINT8 sess_idx, BT_HDR *p_pkt)
+
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ UINT8 *p_param;
+ UINT16 len;
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_CHARSET, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT8(p_cb->msg_param.data.charset, p_param);
+ }
+ else
+ {
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT0("Unable to decode or find charset in application parameter ");
+#endif
+ return FALSE;
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_ATTACH, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT8(p_cb->msg_param.data.attachment, p_param);
+ }
+ else
+ {
+ p_cb->msg_param.data.attachment = FALSE;
+ }
+
+ p_param = bta_mse_read_app_params(p_pkt, BTA_MA_APH_FRAC_REQ, &len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT8(p_cb->msg_param.data.fraction_request, p_param);
+ }
+ else
+ {
+ p_cb->msg_param.data.fraction_request = BTA_MA_FRAC_REQ_NO;
+ }
+
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_get_msglist_path
+**
+** Description Get the path based on received folder name for the get
+** message list
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** p_path - (output) pointer to the folder path
+**
+** Returns BOOLEAN TRUE-get path is successful
+*******************************************************************************/
+BOOLEAN bta_mse_get_msglist_path(UINT8 inst_idx, UINT8 sess_idx)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ char *p_name = p_cb->ml_param.p_name;
+ char *p_path = p_cb->ml_param.p_path;
+ char *p_workdir = p_cb->p_workdir;
+ BOOLEAN status = TRUE;
+#if BTA_MSE_ENABLE_FS_CO == TRUE
+ BOOLEAN is_dir;
+#endif
+
+
+ if (*p_name == '\0')
+ {
+ BCM_STRNCPY_S(p_path, p_bta_fs_cfg->max_path_len+1, p_workdir, p_bta_fs_cfg->max_path_len);
+ }
+ /* Make sure the new path is not too big */
+ /* +1 is for the separator */
+ else if ((strlen(p_workdir)+1+strlen(p_name)) <= p_bta_fs_cfg->max_path_len)
+ {
+ /* create a temporary path for creation attempt */
+ sprintf(p_path, "%s%c%s", p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+#if BTA_MSE_ENABLE_FS_CO == TRUE
+ if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST,
+ &is_dir, bta_mse_cb.app_id)) != BTA_FS_CO_OK) || !is_dir)
+ {
+ status = FALSE;
+ }
+#endif
+ }
+ else
+ {
+ status = FALSE;
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_EVENT2("bta_mse_get_msglist_path status=%d pth=%s",status, p_path );
+#endif
+
+ return status;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_find_bd_addr_match_pm_cb_index
+**
+** Description Finds the PM control block index
+** based on the specified BD address
+**
+** Parameters app_id - app_id
+** p_bd_addr - BD address
+** p_idx - (output) pointer to the MN control
+** block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_pm_cb_index(BD_ADDR p_bd_addr, UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_MSE_NUM_MN ; i ++)
+ {
+ if ((bta_mse_cb.pcb[i].in_use) &&
+ (!memcmp (bta_mse_cb.pcb[i].bd_addr, p_bd_addr, BD_ADDR_LEN)))
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ if (!found) APPL_TRACE_DEBUG2("dbg bta_mse_find_pm_cb_index found=%d index=%d", found, i);
+#endif
+ return found;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_find_avail_pm_cb_idx
+**
+** Description Finds a not in use PM control block index
+**
+** Parameters p_idx - (output) pointer to the PM control block index
+**
+** Returns BOOLEAN - TRUE found
+** FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_mse_find_avail_pm_cb_idx(UINT8 *p_idx)
+{
+ BOOLEAN found=FALSE;
+ UINT8 i;
+
+ for (i=0; i < BTA_MSE_NUM_MN ; i ++)
+ {
+ if (!bta_mse_cb.pcb[i].in_use)
+ {
+ found = TRUE;
+ *p_idx = i;
+ break;
+ }
+ }
+
+#if BTA_MSE_DEBUG == TRUE
+ if (!found) APPL_TRACE_DEBUG2("bta_mse_find_avail_pm_cb_idx found=%d i=%d", found, i);
+#endif
+
+ return found;
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_pm_conn_open
+**
+** Description Determine whether or not bta_sys_conn_open should be called
+**
+** Parameters bd_addr - peer BD address
+**
+** Returns None
+**
+*******************************************************************************/
+void bta_mse_pm_conn_open(BD_ADDR bd_addr)
+{
+ tBTA_MSE_PM_CB *p_pcb;
+ UINT8 idx;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_mse_pm_conn_open");
+#endif
+ if (!bta_mse_find_pm_cb_index(bd_addr, &idx))
+ {
+ if (bta_mse_find_avail_pm_cb_idx(&idx))
+ {
+ p_pcb = BTA_MSE_GET_PM_CB_PTR(idx);
+
+ p_pcb->in_use = TRUE;
+ p_pcb->opened = TRUE;
+ bdcpy(p_pcb->bd_addr, bd_addr);
+ bta_sys_conn_open(BTA_ID_MSE , bta_mse_cb.app_id, bd_addr);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_pm_conn_close
+**
+** Description Determine whether or not bta_sys_conn_close should be called
+**
+** Parameters bd_addr - peer BD address
+**
+** Returns None
+*******************************************************************************/
+void bta_mse_pm_conn_close(BD_ADDR bd_addr)
+{
+ tBTA_MSE_PM_CB *p_pcb;
+ UINT8 i, pm_idx, sess_idx, mn_idx;
+ BOOLEAN found_bd_addr=FALSE;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_DEBUG0("bta_mse_pm_conn_close");
+#endif
+ if (bta_mse_find_pm_cb_index(bd_addr, &pm_idx))
+ {
+ p_pcb = BTA_MSE_GET_PM_CB_PTR(pm_idx);
+ if (p_pcb->opened)
+ {
+ for (i=0; i<BTA_MSE_NUM_INST; i++)
+ {
+ if (bta_mse_find_bd_addr_match_sess_cb_idx(bd_addr, i, &sess_idx))
+ {
+ found_bd_addr = TRUE;
+ break;
+ }
+ }
+
+ if (!found_bd_addr)
+ {
+ if ( bta_mse_find_bd_addr_match_mn_cb_index(bd_addr, &mn_idx))
+ {
+ found_bd_addr = TRUE;
+
+ }
+ }
+
+ if (!found_bd_addr)
+ {
+ memset(p_pcb, 0, sizeof(tBTA_MSE_PM_CB));
+ bta_sys_conn_close(BTA_ID_MSE , bta_mse_cb.app_id, bd_addr);
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_mse_set_ma_oper
+**
+** Description Set MA operation and power management's busy/idle status based on
+** MA operation
+**
+** Parameters inst_idx - Index to the MA instance control block
+** sess_idx - Index to the MA session control block
+** oper - MA operation
+**
+** Returns None
+*******************************************************************************/
+void bta_mse_set_ma_oper(UINT8 inst_idx, UINT8 sess_idx, tBTA_MSE_OPER oper)
+{
+ tBTA_MSE_MA_SESS_CB *p_cb = BTA_MSE_GET_SESS_CB_PTR(inst_idx, sess_idx);
+ tBTA_MSE_MA_SESS_CB *p_scb;
+ tBTA_MSE_MN_CB *p_mcb;
+ tBTA_MSE_PM_CB *p_pcb;
+ UINT8 i, j, pm_idx, mn_idx;
+ BOOLEAN still_busy = FALSE;
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_DEBUG2("bta_mse_set_ma_oper old=%d new=%d", p_cb->oper, oper);
+#endif
+
+ if (p_cb->oper != oper)
+ {
+ p_cb->oper = oper;
+ if (bta_mse_find_pm_cb_index(p_cb->bd_addr, &pm_idx))
+ {
+ p_pcb = BTA_MSE_GET_PM_CB_PTR(pm_idx);
+
+ if (oper != BTA_MSE_OPER_NONE )
+ {
+ if (!p_pcb->busy)
+ {
+ p_pcb->busy = TRUE;
+ bta_sys_busy(BTA_ID_MSE, bta_mse_cb.app_id, p_cb->bd_addr);
+ }
+ }
+ else
+ {
+ if (p_pcb->busy)
+ {
+ for (i=0; i<BTA_MSE_NUM_INST; i++)
+ {
+ if (bta_mse_find_bd_addr_match_sess_cb_idx( p_cb->bd_addr, i, &j) &&
+ (i != inst_idx) && (j != sess_idx))
+ {
+ p_scb = BTA_MSE_GET_SESS_CB_PTR(i, j);
+ if (p_scb->oper != BTA_MSE_OPER_NONE )
+ {
+ still_busy = TRUE;
+ break;
+ }
+ }
+ }
+
+ if ((!still_busy) &&
+ bta_mse_find_bd_addr_match_mn_cb_index( p_cb->bd_addr, &mn_idx))
+ {
+ p_mcb = BTA_MSE_GET_MN_CB_PTR(mn_idx);
+ if (p_mcb->obx_oper != BTA_MSE_MN_OP_NONE )
+ {
+ still_busy = TRUE;
+ }
+ }
+
+ if (!still_busy)
+ {
+ p_pcb->busy = FALSE;
+ bta_sys_idle(BTA_ID_MSE, bta_mse_cb.app_id, p_cb->bd_addr);
+ }
+ }
+ }
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_mse_set_mn_oper
+**
+** Description Set MN operation and power management's busy/idle status based on
+** MN operation
+**
+** Parameters ccb_idx - MN control block index
+** oper - MN operation
+**
+** Returns None
+*******************************************************************************/
+void bta_mse_set_mn_oper(UINT8 ccb_idx, UINT8 oper)
+{
+ tBTA_MSE_MN_CB *p_cb = BTA_MSE_GET_MN_CB_PTR(ccb_idx);
+ tBTA_MSE_MA_SESS_CB *p_scb;
+ tBTA_MSE_MN_CB *p_mcb;
+ tBTA_MSE_PM_CB *p_pcb;
+ UINT8 i, j, pm_idx, mn_idx;
+ BOOLEAN still_busy = FALSE;
+
+#if BTA_MSE_DEBUG == TRUE
+ APPL_TRACE_DEBUG2("dbg bta_mse_set_mn_oper old=%d new=%d", p_cb->obx_oper, oper);
+#endif
+ if (p_cb->obx_oper != oper)
+ {
+ p_cb->obx_oper = oper;
+ if (bta_mse_find_pm_cb_index(p_cb->bd_addr, &pm_idx))
+ {
+ p_pcb = BTA_MSE_GET_PM_CB_PTR(pm_idx);
+
+ if (oper != BTA_MSE_MN_OP_NONE )
+ {
+ if (!p_pcb->busy)
+ {
+ p_pcb->busy = TRUE;
+ bta_sys_busy(BTA_ID_MSE, bta_mse_cb.app_id, p_cb->bd_addr);
+ }
+ }
+ else
+ {
+ if (p_pcb->busy)
+ {
+ for (i=0; i<BTA_MSE_NUM_INST; i++)
+ {
+ if (bta_mse_find_bd_addr_match_sess_cb_idx( p_cb->bd_addr, i, &j))
+ {
+ p_scb = BTA_MSE_GET_SESS_CB_PTR(i, j);
+ if (p_scb->oper != BTA_MSE_OPER_NONE )
+ {
+ still_busy = TRUE;
+ break;
+ }
+ }
+ }
+
+ if ((!still_busy) &&
+ bta_mse_find_bd_addr_match_mn_cb_index(p_cb->bd_addr, &mn_idx) &&
+ (mn_idx != ccb_idx))
+ {
+ p_mcb = BTA_MSE_GET_MN_CB_PTR(mn_idx);
+ if (p_mcb->obx_oper != BTA_MSE_MN_OP_NONE )
+ {
+ still_busy = TRUE;
+ }
+ }
+
+ if (!still_busy)
+ {
+ p_pcb->busy = FALSE;
+ bta_sys_idle(BTA_ID_MSE, bta_mse_cb.app_id, p_cb->bd_addr);
+ }
+ }
+ }
+ }
+ }
+
+}
+
+#endif /* BTA_MSE_INCLUDED */
diff --git a/bta/op/bta_op_fmt.c b/bta/op/bta_op_fmt.c
new file mode 100644
index 0000000..000370a
--- /dev/null
+++ b/bta/op/bta_op_fmt.c
@@ -0,0 +1,804 @@
+/*****************************************************************************
+**
+** Name: bta_op_fmt.c
+**
+** Description: This file contains common functions and data structures
+** used by the OPP object formatting functions.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <string.h>
+#include <ctype.h>
+#include "bta_op_api.h"
+#include "bta_op_fmt.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_ENCODING_LEN 9
+#define BTA_OP_CHARSET_LEN 8
+#define BTA_OP_PARAM_TYPE_HDR_LEN 5
+#define BTA_OP_NUM_NONINLINE_MEDIA 2
+
+const char bta_op_encoding[] = "ENCODING=";
+
+const tBTA_OP_PARAM bta_op_encodings[] =
+{/* the len is (BTA_OP_ENCODING_LEN + 1 + strlen(p_name)) */
+ {NULL, 0},
+ {"QUOTED-PRINTABLE", 26}, /* BTA_OP_ENC_QUOTED_PRINTABLE */
+ {"8BIT", 14}, /* BTA_OP_ENC_8BIT */
+ {"b", 11}, /* BTA_OP_ENC_BINARY */
+// btla-specific ++
+ {"BASE64", 16} /* BTA_OP_ENC_BASE64 */
+// btla-specific --
+};
+
+#define BTA_OP_NUM_ENCODINGS 3
+#define BTA_OP_QP_IDX 1 /* array index for quoted printable in bta_op_encodings */
+
+const char bta_op_charset[] = "CHARSET=";
+
+const char bta_op_param_type_hdr[] = "TYPE=";
+
+const tBTA_OP_PARAM bta_op_charsets[] =
+{/* the len is (BTA_OP_CHARSET_LEN + 1 + strlen(p_name)) */
+ {NULL, 0},
+ {"BIG5", 13}, /* BTA_OP_CHAR_BIG5 */
+ {"EUC-JP", 15}, /* BTA_OP_CHAR_EUC_JP */
+ {"EUC-KR", 15}, /* BTA_OP_CHAR_EUC_KR */
+ {"GB2312", 15}, /* BTA_OP_CHAR_GB2312 */
+ {"ISO-2022-JP", 20}, /* BTA_OP_CHAR_ISO_2022_JP */
+ {"ISO-8859-1", 19}, /* BTA_OP_CHAR_ISO_8859_1 */
+ {"ISO-8859-2", 19}, /* BTA_OP_CHAR_ISO_8859_2 */
+ {"ISO-8859-3", 19}, /* BTA_OP_CHAR_ISO_8859_3 */
+ {"ISO-8859-4", 19}, /* BTA_OP_CHAR_ISO_8859_4 */
+ {"ISO-8859-5", 19}, /* BTA_OP_CHAR_ISO_8859_5 */
+ {"ISO-8859-6", 19}, /* BTA_OP_CHAR_ISO_8859_6 */
+ {"ISO-8859-7", 19}, /* BTA_OP_CHAR_ISO_8859_7 */
+ {"ISO-8859-8", 19}, /* BTA_OP_CHAR_ISO_8859_8 */
+ {"KOI8-R", 15}, /* BTA_OP_CHAR_KOI8_R */
+ {"SHIFT_JIS", 18}, /* BTA_OP_CHAR_SHIFT_JIS */
+ {"UTF-8", 14} /* BTA_OP_CHAR_UTF_8 */
+};
+
+#define BTA_OP_NUM_CHARSETS 16
+
+/* Structure of the 32-bit parameters mask:
+** (same comment is in bta_op_api.h)
+** + property-specific
+** +reserved | + character set
+** | | | + encoding
+** | | | |
+** 0000000000000000 00000000 00000 000
+*/
+#define BTA_OP_GET_PARAM(param, encod, charset, specific) \
+ encod = (UINT8) (param) & 0x00000007; \
+ charset = (UINT8) ((param) >> 3) & 0x0000001F; \
+ specific = (UINT8) ((param) >> 8) & 0x000000FF;
+
+/* mask for properties default 0, filter all */
+static UINT32 bta_op_prop_filter_mask = 0;
+
+const tBTA_OP_PROP_MEDIA bta_op_media[] =
+{
+ {NULL, 2},
+ {"PHOTO", 5},
+ {"SOUND", 5}
+};
+
+/* Place holder constant for safe string functions since there's no way to know how
+** memory is remaining for input parameter to build property.
+** Note: The BCM_STRCPY_S functions should be changed to know how much memory
+** is remaining. When completed this constant can be removed. Also, if safe
+** string functions are not used then this parameter is ignored anyway!
+*/
+#ifndef BTA_OP_REM_MEMORY
+#define BTA_OP_REM_MEMORY 8228
+#endif
+
+/*******************************************************************************
+**
+** Function bta_op_strnicmp
+**
+** Description Case insensitive strncmp.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+INT16 bta_op_strnicmp(const char *pStr1, const char *pStr2, size_t Count)
+{
+ char c1, c2;
+ INT16 v;
+
+ if (Count == 0)
+ return 0;
+
+ do {
+ c1 = *pStr1++;
+ c2 = *pStr2++;
+ /* the casts are necessary when pStr1 is shorter & char is signed */
+ v = (UINT16) tolower(c1) - (UINT16) tolower(c2);
+ } while ((v == 0) && (c1 != '\0') && (--Count > 0));
+
+ return v;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_set_prop_mask
+**
+** Description Set property mask
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_op_set_prop_filter_mask(UINT32 mask)
+{
+ bta_op_prop_filter_mask = mask;
+ return;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_prop_len
+**
+** Description Calculate the length of a property string through lookup
+** tables.
+**
+**
+** Returns Length of string in bytes.
+**
+*******************************************************************************/
+UINT16 bta_op_prop_len(const tBTA_OP_PROP_TBL *p_tbl, tBTA_OP_PROP *p_prop)
+{
+ UINT8 i_e, i_c, i_s;
+ UINT8 len_s = 0;
+ int i;
+
+ /* parse parameters mask */
+ BTA_OP_GET_PARAM(p_prop->parameters, i_e, i_c, i_s);
+
+ /* calculate length of property-specific parameters, if any */
+ if (p_tbl[p_prop->name].p_param_tbl != NULL)
+ {
+ for (i = 1; (i_s != 0) && (i <= p_tbl[p_prop->name].p_param_tbl[0].len); i++)
+ {
+ if (i_s & 1)
+ {
+ len_s += p_tbl[p_prop->name].p_param_tbl[i].len;
+ }
+ i_s >>= 1;
+ }
+ }
+
+ return (p_tbl[p_prop->name].len + len_s + bta_op_charsets[i_c].len +
+ bta_op_encodings[i_e].len + p_prop->len);
+}
+
+/*******************************************************************************
+**
+** Function bta_op_param_conflict
+**
+** Description Check if the parameters of the property for the format
+** conflict/not allowed.
+**
+**
+** Returns TRUE if not allowed, else FALSE
+**
+*******************************************************************************/
+BOOLEAN bta_op_param_conflict(tBTA_OP_SUP_FMT fmt, tBTA_OP_PROP *p_prop)
+{
+ UINT8 i_e, i_c, i_s;
+ BOOLEAN conflict = FALSE;
+
+ if (p_prop->parameters != 0)
+ {
+ BTA_OP_GET_PARAM(p_prop->parameters, i_e, i_c, i_s);
+
+ if (fmt == BTA_OP_FMT_VCARD30)
+ {
+ /* VCard 3.0 does not support CHARSET. If it is present, we
+ should ignore the whole property in the vCard build process */
+ if (bta_op_charsets[i_c].p_name != NULL)
+ conflict = TRUE;
+
+ /* VCard 3.0 only supports 'b' encoding. If any other encoding
+ ex. quoted-printable, is present, then whole property is ignored */
+ if ((bta_op_encodings[i_e].p_name != NULL) && strcmp(bta_op_encodings[i_e].p_name, "b"))
+ conflict = TRUE;
+ }
+ }
+
+ return conflict;
+}
+/*******************************************************************************
+**
+** Function bta_op_add_param
+**
+** Description Add parameter strings to a property string.
+**
+**
+** Returns Pointer to the next byte after the end of the string.
+**
+*******************************************************************************/
+UINT8 *bta_op_add_param(tBTA_OP_SUP_FMT fmt, const tBTA_OP_PROP_TBL *p_tbl, UINT8 *p, tBTA_OP_PROP *p_prop)
+{
+ UINT8 i_e, i_c, i_s;
+ int i;
+ UINT8 bta_op_param_type_delimit = 0;
+
+ if (p_prop->parameters != 0)
+ {
+ BTA_OP_GET_PARAM(p_prop->parameters, i_e, i_c, i_s);
+
+ /* add encoding parameter */
+ if (bta_op_encodings[i_e].p_name != NULL)
+ {
+ *p++ = ';';
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_encoding);
+ p += BTA_OP_ENCODING_LEN;
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_encodings[i_e].p_name);
+ p += bta_op_encodings[i_e].len - BTA_OP_ENCODING_LEN - 1;
+ }
+
+ /* add character set parameter */
+ if (bta_op_charsets[i_c].p_name != NULL)
+ {
+ *p++ = ';';
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_charset);
+ p += BTA_OP_CHARSET_LEN;
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_charsets[i_c].p_name);
+ p += bta_op_charsets[i_c].len - BTA_OP_CHARSET_LEN - 1;
+ }
+
+ /* add any property-specific parameters */
+ if (p_tbl[p_prop->name].p_param_tbl != NULL)
+ {
+ for (i = 1; (i_s != 0) && (i <= p_tbl[p_prop->name].p_param_tbl[0].len); i++)
+ {
+ if (i_s & 1)
+ {
+ if (bta_op_param_type_delimit)
+ {
+ *p++ = ',';
+ }
+ else
+ {
+ *p++ = ';';
+
+ if (fmt == BTA_OP_FMT_VCARD30)
+ {
+ BCM_STRNCPY_S((char *) p, BTA_OP_PARAM_TYPE_HDR_LEN+1, bta_op_param_type_hdr, BTA_OP_PARAM_TYPE_HDR_LEN);
+ p += BTA_OP_PARAM_TYPE_HDR_LEN;
+ bta_op_param_type_delimit++;
+ }
+ }
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, p_tbl[p_prop->name].p_param_tbl[i].p_name);
+ p += p_tbl[p_prop->name].p_param_tbl[i].len - 1;
+ }
+ i_s >>= 1;
+ }
+ }
+ }
+ else if (p_prop->p_param)
+ {
+ *p++ = ';';
+ memcpy((char *) p, p_prop->p_param, p_prop->param_len);
+ p += p_prop->param_len;
+ }
+
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_add_media_param
+**
+** Description Add parameter strings to a media property string.
+**
+**
+** Returns Pointer to the next byte after the end of the string.
+**
+*******************************************************************************/
+UINT8 *bta_op_add_media_param(const tBTA_OP_PROP_TBL *p_tbl, UINT8 *p, tBTA_OP_PROP *p_prop)
+{
+ UINT8 i_e, i_c, i_s;
+ int i;
+
+ if (p_prop->parameters != 0)
+ {
+ BTA_OP_GET_PARAM(p_prop->parameters, i_e, i_c, i_s);
+
+ /* add encoding parameter */
+ if (bta_op_encodings[i_e].p_name != NULL)
+ {
+ *p++ = ';';
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_encoding);
+ p += BTA_OP_ENCODING_LEN;
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, bta_op_encodings[i_e].p_name);
+ p += bta_op_encodings[i_e].len - BTA_OP_ENCODING_LEN - 1;
+ }
+
+ /* add any property-specific parameters */
+ if (p_tbl[p_prop->name].p_param_tbl != NULL)
+ {
+ for (i = 1; (i_s != 0) && (i <= p_tbl[p_prop->name].p_param_tbl[0].len); i++)
+ {
+ if (i_s & 1)
+ {
+ *p++ = ';';
+
+ /* Add "TYPE=" to non-referenced (inline) media */
+ if (i > BTA_OP_NUM_NONINLINE_MEDIA)
+ {
+ BCM_STRNCPY_S((char *) p, BTA_OP_PARAM_TYPE_HDR_LEN+1, bta_op_param_type_hdr, BTA_OP_PARAM_TYPE_HDR_LEN);
+ p += BTA_OP_PARAM_TYPE_HDR_LEN;
+ }
+
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, p_tbl[p_prop->name].p_param_tbl[i].p_name);
+ p += p_tbl[p_prop->name].p_param_tbl[i].len - 1;
+ break;
+ }
+ i_s >>= 1;
+ }
+ }
+ }
+ else if (p_prop->p_param)
+ {
+ *p++ = ';';
+ memcpy((char *) p, p_prop->p_param, p_prop->param_len);
+ p += p_prop->param_len;
+ }
+
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_get_property_by_name
+**
+** Description Get the property user data by name.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if there is no property user data.
+**
+*******************************************************************************/
+tBTA_OP_STATUS bta_op_get_property_by_name(const tBTA_OP_PROP_TBL *p_tbl, UINT8 *p_name,
+ tBTA_OP_PROP *p_prop, UINT8 num_prop, UINT8 *p_data,
+ UINT16 *p_len)
+{
+ int i, j;
+ tBTA_OP_STATUS result = BTA_OP_FAIL;
+
+ /* for each property */
+ for(i = 0; num_prop != 0; num_prop--, i++)
+ {
+ /* verify property is valid */
+ if ((p_prop[i].name == 0) || (p_prop[i].name > p_tbl[0].len))
+ {
+ result = BTA_OP_FAIL;
+ break;
+ }
+
+ j = p_prop[i].name;
+
+ if (bta_op_strnicmp(p_tbl[j].p_name, (char *) p_name,
+ (p_tbl[j].len - BTA_OP_PROP_OVHD)) == 0)
+ {
+ memcpy(p_data, p_prop[i].p_data, p_prop[i].len);
+ *p_len = p_prop[i].len;
+ result = BTA_OP_OK;
+ break;
+ }
+ }
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_build_obj
+**
+** Description Build an object from property data supplied by the user.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS bta_op_build_obj(const tBTA_OP_OBJ_TBL *p_bld, UINT8 *p_data,
+ UINT16 *p_len, tBTA_OP_PROP *p_prop, UINT8 num_prop)
+{
+ int i,j;
+ tBTA_OP_STATUS result = BTA_OP_OK;
+ UINT8 *p = p_data;
+
+ /* sanity check length */
+ if (*p_len < p_bld->min_len)
+ {
+ result = BTA_OP_MEM;
+ }
+ else
+ {
+ /* adjust p_len to amount of free space minus start and end */
+ *p_len -= p_bld->min_len;
+
+ /* add begin, version */
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, p_bld->p_begin_str);
+ p += p_bld->begin_len;
+
+ /* for each property */
+ for(i = 0; num_prop != 0; num_prop--, i++)
+ {
+ /* verify property is valid */
+ if ((p_prop[i].name == 0) || (p_prop[i].name > p_bld->p_tbl[0].len))
+ {
+ result = BTA_OP_FAIL;
+ break;
+ }
+
+ /* verify property will fit */
+ if (bta_op_prop_len(p_bld->p_tbl, &p_prop[i]) > (p_data + p_bld->begin_len + *p_len - p))
+ {
+ result = BTA_OP_MEM;
+ break;
+ }
+
+ /* check for filter */
+ if (bta_op_prop_filter_mask !=0 && p_bld->p_prop_filter_mask_tbl != NULL &&
+ p_prop[i].name <= p_bld->p_prop_filter_mask_tbl->len)
+ {
+ if (!(bta_op_prop_filter_mask & p_bld->p_prop_filter_mask_tbl->p_prop_filter_mask[p_prop[i].name]))
+ continue;
+ }
+
+ /* Check if the combination of parameters are allowed for
+ the format we are building */
+ if (bta_op_param_conflict(p_bld->fmt, &p_prop[i]))
+ continue;
+
+ /* add property string */
+ BCM_STRCPY_S((char *) p, BTA_OP_REM_MEMORY, p_bld->p_tbl[p_prop[i].name].p_name);
+ p += p_bld->p_tbl[p_prop[i].name].len - BTA_OP_PROP_OVHD;
+
+ for (j= bta_op_media[0].len; j > 0; j--)
+ {
+ if (!bta_op_strnicmp(bta_op_media[j].media_name, p_bld->p_tbl[p_prop[i].name].p_name, bta_op_media[j].len))
+ {
+ p = bta_op_add_media_param(p_bld->p_tbl, p, &p_prop[i]);
+ break;
+ }
+ }
+
+ if (!j)
+ {
+ /* add property parameters */
+ p = bta_op_add_param(p_bld->fmt, p_bld->p_tbl, p, &p_prop[i]);
+ }
+
+ /* add user data */
+// btla-specific ++
+ if(p_prop[i].name != BTA_OP_VCARD_CALL) // If the data is call date-time, use ';' instead of ':'
+ {
+ *p++ = ':';
+ }
+ else
+ {
+ *p++ = ';';
+ }
+// btla-specific --
+
+ memcpy(p, p_prop[i].p_data, p_prop[i].len);
+ p += p_prop[i].len;
+ *p++ = '\r';
+ *p++ = '\n';
+ }
+
+ /* add in end */
+ memcpy(p, p_bld->p_end_str, p_bld->end_len);
+ p += p_bld->end_len;
+ }
+
+ *p_len = (UINT16) (p - p_data);
+ return result;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_nextline
+**
+** Description Scan to beginning of next property text line.
+**
+**
+** Returns Pointer to beginning of property or NULL if end of
+** data reached.
+**
+*******************************************************************************/
+static UINT8 *bta_op_nextline(UINT8 *p, UINT8 *p_end, BOOLEAN qp)
+{
+// btla-specific ++
+ if (*p == '\r')
+ {
+ p--;
+ }
+// btla-specific --
+
+ if ((p_end - p) > 3)
+ {
+ p_end -= 3;
+ while (p < p_end)
+ {
+ if (*(++p) == '\r')
+ {
+ if (*(p + 1) == '\n')
+ {
+ if (qp)
+ {
+ if (*(p - 1) == '=')
+ {
+ /* this is a soft break for quoted-printable*/
+ continue;
+ }
+ }
+
+ if ((*(p + 2) != ' ') && (*(p + 2) != '\t'))
+ {
+ return(p + 2);
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_scantok
+**
+** Description Scan a line for one or more tokens.
+**
+**
+** Returns Pointer to token or NULL if end of data reached.
+**
+*******************************************************************************/
+static UINT8 *bta_op_scantok(UINT8 *p, UINT8 *p_end, const char *p_tok)
+{
+ int i;
+ UINT8 num_tok = strlen(p_tok);
+
+ for (; p < p_end; p++)
+ {
+ for (i = 0; i < num_tok; i++)
+ {
+ if (*p == p_tok[i])
+ {
+ return p;
+ }
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_scanstr
+**
+** Description Scan for a matching string.
+**
+**
+** Returns Pointer to end of match or NULL if end of data reached.
+**
+*******************************************************************************/
+UINT8 *bta_op_scanstr(UINT8 *p, UINT8 *p_end, const char *p_str)
+{
+ int len = strlen(p_str);
+
+ for (;;)
+ {
+ /* check for match */
+ if (strncmp((char *) p, p_str, len) == 0)
+ {
+ p += len;
+ break;
+ }
+ /* no match; skip to next line, checking for end */
+ else if ((p = bta_op_nextline(p, p_end, FALSE)) == NULL)
+ {
+ break;
+ }
+ }
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function bta_op_parse_obj
+**
+** Description Parse an object.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS bta_op_parse_obj(const tBTA_OP_OBJ_TBL *p_prs, tBTA_OP_PROP *p_prop,
+ UINT8 *p_num_prop, UINT8 *p_data, UINT16 len)
+{
+ UINT32 j;
+ UINT8 *p_s, *p_e;
+ tBTA_OP_STATUS result = BTA_OP_OK;
+ UINT8 max_prop = *p_num_prop;
+ UINT8 *p_end = p_data + len;
+ UINT8 prop_name = 0;
+ BOOLEAN qp=FALSE;
+
+ *p_num_prop = 0;
+
+ /* sanity check length */
+ if (len < p_prs->min_len)
+ {
+ return BTA_OP_FAIL;
+ }
+
+ /* find beginning */
+ if ((p_s = bta_op_scanstr(p_data, p_end, p_prs->p_begin_str)) == NULL)
+ {
+ return BTA_OP_FAIL;
+ }
+
+ while (*p_num_prop < max_prop)
+ {
+ /* scan for next delimiter */
+ if ((p_e = bta_op_scantok(p_s, p_end, ".;:")) == NULL)
+ {
+ break;
+ }
+
+ /* deal with grouping delimiter */
+ if (*p_e == '.')
+ {
+ p_s = p_e + 1;
+ if ((p_e = bta_op_scantok(p_s, p_end, ";:")) == NULL)
+ {
+ break;
+ }
+ }
+
+ /* we found a property; see if it matches anything in our list */
+ for (j = 1; j <= p_prs->p_tbl[0].len; j++)
+ {
+ if (bta_op_strnicmp(p_prs->p_tbl[j].p_name, (char *) p_s,
+ (p_prs->p_tbl[j].len - BTA_OP_PROP_OVHD)) == 0)
+ {
+ p_prop[*p_num_prop].name = prop_name = j;
+ p_prop[*p_num_prop].parameters = 0;
+ break;
+ }
+ }
+
+ /* if not in our list we can't parse it; continue */
+ if (j > p_prs->p_tbl[0].len)
+ {
+ if ((p_s = bta_op_nextline(p_e, p_end, FALSE)) == NULL)
+ {
+ break;
+ }
+ continue;
+ }
+
+ /* now parse out all the parameters */
+ if (*p_e == ';')
+ {
+ while ((*p_e == ';') || (*p_e == ','))
+ {
+ p_s = p_e + 1;
+
+ if ((p_e = bta_op_scantok(p_s, p_end, ",;:")) == NULL)
+ {
+ break;
+ }
+
+ /* we found a parameter; see if it matches anything */
+
+ /* check for encoding */
+ qp = FALSE;
+ if (bta_op_strnicmp(bta_op_encoding, (char *) p_s, BTA_OP_ENCODING_LEN) == 0)
+ {
+ p_s += BTA_OP_ENCODING_LEN;
+ for (j = 1; j <= BTA_OP_NUM_ENCODINGS; j++)
+ {
+ if (bta_op_strnicmp(bta_op_encodings[j].p_name, (char *) p_s,
+ (bta_op_encodings[j].len - BTA_OP_ENCODING_LEN - 1)) == 0)
+ {
+ if (j == BTA_OP_QP_IDX)
+ {
+ /* encoding = quoted-printable*/
+ qp= TRUE;
+ }
+ p_prop[*p_num_prop].parameters |= j;
+ break;
+ }
+ }
+ }
+ /* check for charset */
+ else if (bta_op_strnicmp(bta_op_charset, (char *) p_s, BTA_OP_CHARSET_LEN) == 0)
+ {
+ p_s += BTA_OP_CHARSET_LEN;
+ for (j = 1; j <= BTA_OP_NUM_CHARSETS; j++)
+ {
+ if (bta_op_strnicmp(bta_op_charsets[j].p_name, (char *) p_s,
+ (bta_op_charsets[j].len - BTA_OP_CHARSET_LEN - 1)) == 0)
+ {
+ p_prop[*p_num_prop].parameters |= j << 3;
+ break;
+ }
+ }
+ }
+ /* check for property-specific parameters */
+ else if (p_prs->p_tbl[prop_name].p_param_tbl != NULL)
+ {
+
+ /* Check for "TYPE=" */
+ if (!bta_op_strnicmp((char *)p_s, bta_op_param_type_hdr, BTA_OP_PARAM_TYPE_HDR_LEN))
+ {
+ p_s += BTA_OP_PARAM_TYPE_HDR_LEN;
+ }
+
+ for (j = p_prs->p_tbl[prop_name].p_param_tbl[0].len; j > 0; j--)
+ {
+ if (bta_op_strnicmp(p_prs->p_tbl[prop_name].p_param_tbl[j].p_name,
+ (char *) p_s, (p_prs->p_tbl[prop_name].p_param_tbl[j].len - 1)) == 0)
+ {
+ p_prop[*p_num_prop].parameters |= ((UINT32) 1) << (j + 7);
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* if this the start of the param */
+ if (!p_prop[*p_num_prop].p_param)
+ p_prop[*p_num_prop].p_param = p_s;
+ if (*p_e == ':')
+ p_prop[*p_num_prop].param_len += (p_e - p_s);
+ else
+ p_prop[*p_num_prop].param_len += (p_e - p_s + 1);
+ }
+ }
+ }
+
+ if (p_e == NULL)
+ {
+ break;
+ }
+
+ /* go to start of next property */
+ p_s = p_e + 1;
+ if ((p_e = bta_op_nextline(p_s, p_end, qp)) == NULL)
+ {
+ break;
+ }
+
+ /* save property info */
+ p_prop[*p_num_prop].p_data = p_s;
+ p_prop[*p_num_prop].len = (UINT16) (p_e - p_s - 2);
+// btla-specific ++
+ if (p_prop[*p_num_prop].len)
+ {
+ (*p_num_prop)++;
+ }
+// btla-specific --
+ p_s = p_e;
+ }
+ return result;
+}
+
diff --git a/bta/op/bta_op_fmt.h b/bta/op/bta_op_fmt.h
new file mode 100644
index 0000000..29bb40c
--- /dev/null
+++ b/bta/op/bta_op_fmt.h
@@ -0,0 +1,92 @@
+/*****************************************************************************
+**
+** Name: bta_op_fmt.h
+**
+** Description: This is the interface file for common functions and data
+** types used by the OPP object formatting functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_OP_FMT_H
+#define BTA_OP_FMT_H
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_PROP_OVHD 3
+
+/*****************************************************************************
+** Data types
+*****************************************************************************/
+
+enum {
+ BTA_OP_FMT_NONE=0,
+ BTA_OP_FMT_VCARD21,
+ BTA_OP_FMT_VCARD30,
+ BTA_OP_FMT_VCAL10,
+ BTA_OP_FMT_VNOTE11
+};
+
+/*Supported formats */
+typedef UINT8 tBTA_OP_SUP_FMT;
+
+typedef struct
+{
+ const char *p_name;
+ UINT8 len;
+} tBTA_OP_PARAM;
+
+typedef struct
+{
+ const char *p_name;
+ const tBTA_OP_PARAM *p_param_tbl;
+ UINT8 len;
+} tBTA_OP_PROP_TBL;
+
+
+typedef struct
+{
+ const UINT32 *p_prop_filter_mask;
+ UINT8 len;
+} tBTA_OP_PROP_FILTER_MASK_TBL;
+
+typedef struct
+{
+ const tBTA_OP_PROP_TBL *p_tbl;
+ tBTA_OP_SUP_FMT fmt;
+ const char *p_begin_str;
+ const char *p_end_str;
+ UINT8 begin_len;
+ UINT8 end_len;
+ UINT8 min_len;
+ const tBTA_OP_PROP_FILTER_MASK_TBL *p_prop_filter_mask_tbl;
+} tBTA_OP_OBJ_TBL;
+
+typedef struct
+{
+ const char *media_name;
+ UINT8 len;
+} tBTA_OP_PROP_MEDIA;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern tBTA_OP_STATUS bta_op_build_obj(const tBTA_OP_OBJ_TBL *p_bld,
+ UINT8 *p_data, UINT16 *p_len,
+ tBTA_OP_PROP *p_prop, UINT8 num_prop);
+
+extern tBTA_OP_STATUS bta_op_parse_obj(const tBTA_OP_OBJ_TBL *p_prs,
+ tBTA_OP_PROP *p_prop, UINT8 *p_num_prop,
+ UINT8 *p_data, UINT16 len);
+extern tBTA_OP_STATUS bta_op_get_property_by_name(const tBTA_OP_PROP_TBL *p_tbl, UINT8 *p_name,
+ tBTA_OP_PROP *p_prop, UINT8 num_prop, UINT8 *p_data,
+ UINT16 *p_len);
+extern UINT8 *bta_op_scanstr(UINT8 *p, UINT8 *p_end, const char *p_str);
+extern void bta_op_set_prop_filter_mask(UINT32 mask);
+
+#endif /* BTA_OP_FMT_H */
+
diff --git a/bta/op/bta_op_vcal.c b/bta/op/bta_op_vcal.c
new file mode 100644
index 0000000..79aef02
--- /dev/null
+++ b/bta/op/bta_op_vcal.c
@@ -0,0 +1,158 @@
+/*****************************************************************************
+**
+** Name: bta_op_vcal.c
+**
+** Description: This file contains functions for parsing and building
+** vCal objects.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_op_api.h"
+#include "bta_op_fmt.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_TODO_BEGIN_LEN 43
+#define BTA_OP_TODO_END_LEN 26
+
+#define BTA_OP_TODO_MIN_LEN (BTA_OP_TODO_BEGIN_LEN + BTA_OP_TODO_END_LEN)
+
+#define BTA_OP_EVENT_BEGIN_LEN 44
+#define BTA_OP_EVENT_END_LEN 27
+
+#define BTA_OP_EVENT_MIN_LEN (BTA_OP_EVENT_BEGIN_LEN + BTA_OP_EVENT_END_LEN)
+
+#define BTA_OP_VCAL_BEGIN_LEN 17
+#define BTA_OP_VCAL_END_LEN 15
+#define BTA_OP_VCAL_MIN_LEN (BTA_OP_VCAL_BEGIN_LEN + BTA_OP_VCAL_END_LEN)
+#define BTA_OP_BEGIN_OFFSET 30
+
+const char bta_op_vcal_begin[] = "BEGIN:VCALENDAR\r\n";
+
+const char bta_op_todo_begin[] = "BEGIN:VCALENDAR\r\nVERSION:1.0\r\nBEGIN:VTODO\r\n";
+
+const char bta_op_todo_end[] = "END:VTODO\r\nEND:VCALENDAR\r\n";
+
+const char bta_op_event_begin[] = "BEGIN:VCALENDAR\r\nVERSION:1.0\r\nBEGIN:VEVENT\r\n";
+
+const char bta_op_event_end[] = "END:VEVENT\r\nEND:VCALENDAR\r\n";
+
+const tBTA_OP_PROP_TBL bta_op_vcal_tbl[] =
+{
+ {NULL, NULL, 11}, /* Number of elements in array */
+ {"CATEGORIES", NULL, 13}, /* BTA_OP_VCAL_CATEGORIES */
+ {"COMPLETED", NULL, 12}, /* BTA_OP_VCAL_COMPLETED */
+ {"DESCRIPTION", NULL, 14}, /* BTA_OP_VCAL_DESCRIPTION */
+ {"DTEND", NULL, 8}, /* BTA_OP_VCAL_DTEND */
+ {"DTSTART", NULL, 10}, /* BTA_OP_VCAL_DTSTART */
+ {"DUE", NULL, 6}, /* BTA_OP_VCAL_DUE */
+ {"LOCATION", NULL, 11}, /* BTA_OP_VCAL_LOCATION */
+ {"PRIORITY", NULL, 11}, /* BTA_OP_VCAL_PRIORITY */
+ {"STATUS", NULL, 9}, /* BTA_OP_VCAL_STATUS */
+ {"SUMMARY", NULL, 10}, /* BTA_OP_VCAL_SUMMARY */
+ {"X-IRMC-LUID", NULL, 14} /* BTA_OP_VCAL_LUID */
+};
+
+const tBTA_OP_OBJ_TBL bta_op_todo_bld =
+{
+ bta_op_vcal_tbl,
+ BTA_OP_FMT_VCAL10,
+ bta_op_todo_begin,
+ bta_op_todo_end,
+ BTA_OP_TODO_BEGIN_LEN,
+ BTA_OP_TODO_END_LEN,
+ BTA_OP_TODO_MIN_LEN
+};
+
+const tBTA_OP_OBJ_TBL bta_op_event_bld =
+{
+ bta_op_vcal_tbl,
+ BTA_OP_FMT_VCAL10,
+ bta_op_event_begin,
+ bta_op_event_end,
+ BTA_OP_EVENT_BEGIN_LEN,
+ BTA_OP_EVENT_END_LEN,
+ BTA_OP_EVENT_MIN_LEN
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcal_prs =
+{
+ bta_op_vcal_tbl,
+ BTA_OP_FMT_VCAL10,
+ bta_op_vcal_begin,
+ NULL,
+ BTA_OP_VCAL_BEGIN_LEN,
+ BTA_OP_VCAL_END_LEN,
+ BTA_OP_VCAL_MIN_LEN
+};
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildCal
+**
+** Description Build a vCal 1.0 object. The input to this function is an
+** array of vCaalproperties and a pointer to memory to store
+** the card. The output is a formatted vCal.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpBuildCal(UINT8 *p_cal, UINT16 *p_len, tBTA_OP_PROP *p_prop,
+ UINT8 num_prop, tBTA_OP_VCAL vcal_type)
+{
+ tBTA_OP_OBJ_TBL *p_bld;
+
+ if (vcal_type == BTA_OP_VCAL_EVENT)
+ {
+ p_bld = (tBTA_OP_OBJ_TBL *) &bta_op_event_bld;
+ }
+ else
+ {
+ p_bld = ( tBTA_OP_OBJ_TBL *) &bta_op_todo_bld;
+ }
+
+ return bta_op_build_obj(p_bld, p_cal, p_len, p_prop, num_prop);
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpParseCal
+**
+** Description Parse a vCal object. The input to this function is a
+** pointer to vCal data. The output is an array of parsed
+** vCal properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpParseCal(tBTA_OP_PROP *p_prop, UINT8 *p_num_prop, UINT8 *p_cal,
+ UINT16 len, tBTA_OP_VCAL *p_vcal_type)
+{
+ if (bta_op_scanstr(p_cal, (p_cal + len), &bta_op_todo_begin[BTA_OP_BEGIN_OFFSET]) != NULL)
+ {
+ *p_vcal_type = BTA_OP_VCAL_TODO;
+ }
+ else if (bta_op_scanstr(p_cal, (p_cal + len), &bta_op_event_begin[BTA_OP_BEGIN_OFFSET]) != NULL)
+ {
+ *p_vcal_type = BTA_OP_VCAL_EVENT;
+ }
+ else
+ {
+ *p_num_prop = 0;
+ return BTA_OP_FAIL;
+ }
+
+ return bta_op_parse_obj(&bta_op_vcal_prs, p_prop, p_num_prop, p_cal, len);
+}
+
diff --git a/bta/op/bta_op_vcard.c b/bta/op/bta_op_vcard.c
new file mode 100644
index 0000000..6a278ba
--- /dev/null
+++ b/bta/op/bta_op_vcard.c
@@ -0,0 +1,310 @@
+/*****************************************************************************
+**
+** Name: bta_op_vcard.c
+**
+** Description: This file contains functions for parsing and building
+** vCard objects.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_op_api.h"
+#include "bta_op_fmt.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_VCARD_BEGIN_LEN 26
+#define BTA_OP_VCARD_END_LEN 11
+
+#define BTA_OP_VCARD_MIN_LEN (BTA_OP_VCARD_BEGIN_LEN + BTA_OP_VCARD_END_LEN)
+
+const char bta_op_vcard_prs_begin[] = "BEGIN:VCARD\r\n";
+
+const char bta_op_vcard_21_begin[] = "BEGIN:VCARD\r\nVERSION:2.1\r\n";
+
+const char bta_op_vcard_30_begin[] = "BEGIN:VCARD\r\nVERSION:3.0\r\n";
+
+const char bta_op_vcard_end[] = "END:VCARD\r\n";
+
+const tBTA_OP_PARAM bta_op_vcard_adr[] =
+{
+ {NULL, 6}, /* Number of elements in array */
+ {"DOM", 4}, /* BTA_OP_ADR_DOM */
+ {"INTL", 5}, /* BTA_OP_ADR_INTL */
+ {"POSTAL", 7}, /* BTA_OP_ADR_POSTAL */
+ {"PARCEL", 7}, /* BTA_OP_ADR_PARCEL */
+ {"HOME", 5}, /* BTA_OP_ADR_HOME */
+ {"WORK", 5} /* BTA_OP_ADR_WORK */
+};
+
+const tBTA_OP_PARAM bta_op_vcard_email[] =
+{
+ {NULL, 3}, /* Number of elements in array */
+ {"PREF", 5}, /* BTA_OP_EMAIL_PREF */
+ {"INTERNET", 9}, /* BTA_OP_EMAIL_INTERNET */
+ {"X400", 5} /* BTA_OP_EMAIL_X400 */
+};
+
+const tBTA_OP_PARAM bta_op_vcard_tel[] =
+{
+ {NULL, 8}, /* Number of elements in array */
+ {"PREF", 5}, /* BTA_OP_TEL_PREF */
+ {"WORK", 5}, /* BTA_OP_TEL_WORK */
+ {"HOME", 5}, /* BTA_OP_TEL_HOME */
+ {"VOICE", 6}, /* BTA_OP_TEL_VOICE */
+ {"FAX", 4}, /* BTA_OP_TEL_FAX */
+ {"MSG", 4}, /* BTA_OP_TEL_MSG */
+ {"CELL", 5}, /* BTA_OP_TEL_CELL */
+ {"PAGER", 6} /* BTA_OP_TEL_PAGER */
+};
+
+const tBTA_OP_PARAM bta_op_vcard_photo[] =
+{
+ {NULL, 4}, /* Number of elements in array */
+ {"VALUE=URI", 10}, /* BTA_OP_PHOTO_VALUE_URI */
+ {"VALUE=URL", 10}, /* BTA_OP_PHOTO_VALUE_URL */
+ {"JPEG", 5}, /* BTA_OP_PHOTO_TYPE_JPEG */
+ {"GIF", 4} /* BTA_OP_PHOTO_TYPE_GIF */
+};
+
+const tBTA_OP_PARAM bta_op_vcard_sound[] =
+{
+ {NULL, 4}, /* Number of elements in array */
+ {"VALUE=URI", 10}, /* BTA_OP_SOUND_VALUE_URI */
+ {"VALUE=URL", 10}, /* BTA_OP_SOUND_VALUE_URL */
+ {"BASIC", 6}, /* BTA_OP_SOUND_TYPE_BASIC */
+ {"WAVE", 5} /* BTA_OP_SOUND_TYPE_WAVE */
+};
+
+const tBTA_OP_PROP_TBL bta_op_vcard_tbl[] =
+{
+ {NULL, NULL, 15}, /* Number of elements in array */
+ {"ADR", bta_op_vcard_adr, 6}, /* BTA_OP_VCARD_ADR */
+ {"EMAIL", bta_op_vcard_email, 8}, /* BTA_OP_VCARD_EMAIL */
+ {"FN", NULL, 5}, /* BTA_OP_VCARD_FN */
+ {"NOTE", NULL, 7}, /* BTA_OP_VCARD_NOTE */
+ {"NICKNAME", NULL, 11}, /* BTA_OP_VACRD_NICKNAME */
+ {"N", NULL, 4}, /* BTA_OP_VCARD_N */
+ {"ORG", NULL, 6}, /* BTA_OP_VCARD_ORG */
+ {"TEL", bta_op_vcard_tel, 6}, /* BTA_OP_VCARD_TEL */
+ {"TITLE", NULL, 8}, /* BTA_OP_VCARD_TITLE */
+ {"URL", NULL, 6}, /* BTA_OP_VCARD_URL */
+ {"X-IRMC-LUID", NULL, 14}, /* BTA_OP_VNOTE_LUID */
+ {"BDAY", NULL, 7}, /* BTA_OP_VCARD_BDAY */
+ {"PHOTO", bta_op_vcard_photo, 8}, /* BTA_OP_VCARD_PHOTO */
+ {"SOUND", bta_op_vcard_sound, 8}, /* BTA_OP_VCARD_SOUND */
+ {"X-IRMC-CALL-DATETIME", NULL, 23} /* BTA_OP_VCARD_CALL */
+};
+
+const UINT32 bta_op_vcard_prop_filter_mask[] =
+{
+/* table index should be the same as the prop table above */
+ BTA_OP_FILTER_ALL,
+ BTA_OP_FILTER_ADR,
+ BTA_OP_FILTER_EMAIL,
+ BTA_OP_FILTER_FN,
+ BTA_OP_FILTER_NOTE,
+ BTA_OP_FILTER_NICKNAME,
+ BTA_OP_FILTER_N,
+ BTA_OP_FILTER_ORG,
+ BTA_OP_FILTER_TEL,
+ BTA_OP_FILTER_TITLE,
+ BTA_OP_FILTER_URL,
+ BTA_OP_FILTER_UID,
+ BTA_OP_FILTER_BDAY,
+ BTA_OP_FILTER_PHOTO,
+ BTA_OP_FILTER_SOUND,
+ BTA_OP_FILTER_TIME_STAMP
+};
+
+const tBTA_OP_PROP_FILTER_MASK_TBL bta_op_vcard_prop_filter_mask_tbl =
+{
+ bta_op_vcard_prop_filter_mask,
+ 15
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcard_21_bld =
+{
+ bta_op_vcard_tbl,
+ BTA_OP_FMT_VCARD21,
+ bta_op_vcard_21_begin,
+ bta_op_vcard_end,
+ BTA_OP_VCARD_BEGIN_LEN,
+ BTA_OP_VCARD_END_LEN,
+ BTA_OP_VCARD_MIN_LEN,
+ &bta_op_vcard_prop_filter_mask_tbl
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcard_30_bld =
+{
+ bta_op_vcard_tbl,
+ BTA_OP_FMT_VCARD30,
+ bta_op_vcard_30_begin,
+ bta_op_vcard_end,
+ BTA_OP_VCARD_BEGIN_LEN,
+ BTA_OP_VCARD_END_LEN,
+ BTA_OP_VCARD_MIN_LEN,
+ &bta_op_vcard_prop_filter_mask_tbl
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcard_21_prs =
+{
+ bta_op_vcard_tbl,
+ BTA_OP_FMT_VCARD21,
+ bta_op_vcard_prs_begin,
+ bta_op_vcard_end,
+ BTA_OP_VCARD_BEGIN_LEN,
+ BTA_OP_VCARD_END_LEN,
+ BTA_OP_VCARD_MIN_LEN,
+ NULL
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vcard_30_prs =
+{
+ bta_op_vcard_tbl,
+ BTA_OP_FMT_VCARD30,
+ bta_op_vcard_prs_begin,
+ bta_op_vcard_end,
+ BTA_OP_VCARD_BEGIN_LEN,
+ BTA_OP_VCARD_END_LEN,
+ BTA_OP_VCARD_MIN_LEN,
+ NULL
+};
+
+
+/*******************************************************************************
+**
+** Function bta_op_get_card_fmt
+**
+** Description Finds the vCard format contained in buffer pointed by p_card
+**
+**
+** Returns Vcard Format BTA_OP_VCARD21_FMT/BTA_OP_VCARD30_FMT else
+** BTA_OP_OTHER_FMT
+**
+*******************************************************************************/
+static tBTA_OP_SUP_FMT bta_op_get_card_fmt(UINT8 *p_data, UINT16 len)
+{
+ UINT8 *p_end = p_data + len;
+
+ if (bta_op_scanstr(p_data, p_end, bta_op_vcard_21_begin) != NULL)
+ {
+ return BTA_OP_FMT_VCARD21;
+ }
+ else if (bta_op_scanstr(p_data, p_end, bta_op_vcard_30_begin) != NULL)
+ {
+ return BTA_OP_FMT_VCARD30;
+ }
+ else
+ {
+ return BTA_OP_FMT_NONE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildCard
+**
+** Description Build a vCard object. The input to this function is
+** requested format(2.1/3.0), an array of vCard properties
+** and a pointer to memory to store the card.
+** The output is a formatted vCard.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpBuildCard(UINT8 *p_card, UINT16 *p_len, tBTA_OP_FMT fmt,
+ tBTA_OP_PROP *p_prop, UINT8 num_prop)
+{
+ if(fmt == BTA_OP_VCARD21_FMT)
+ {
+ return bta_op_build_obj(&bta_op_vcard_21_bld, p_card, p_len, p_prop, num_prop);
+ }
+ else if(fmt == BTA_OP_VCARD30_FMT)
+ {
+ return bta_op_build_obj(&bta_op_vcard_30_bld, p_card, p_len, p_prop, num_prop);
+ }
+ else
+ {
+ *p_len = 0;
+ return BTA_OP_FAIL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpSetCardPropFilterMask
+**
+** Description Set Property Filter Mask
+**
+**
+** Returns
+**
+*******************************************************************************/
+void BTA_OpSetCardPropFilterMask(UINT32 mask)
+{
+ bta_op_set_prop_filter_mask(mask);
+ return;
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpParseCard
+**
+** Description Parse a vCard 2.1 object. The input to this function is
+** a pointer to vCard data. The output is an array of parsed
+** vCard properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpParseCard(tBTA_OP_PROP *p_prop, UINT8 *p_num_prop,
+ UINT8 *p_card, UINT16 len)
+{
+ tBTA_OP_SUP_FMT fmt = bta_op_get_card_fmt(p_card, len);
+
+ if (fmt == BTA_OP_FMT_VCARD21)
+ {
+ return bta_op_parse_obj(&bta_op_vcard_21_prs, p_prop, p_num_prop, p_card, len);
+ }
+ else if(fmt == BTA_OP_FMT_VCARD30)
+ {
+ return bta_op_parse_obj(&bta_op_vcard_30_prs, p_prop, p_num_prop, p_card, len);
+ }
+ else
+ {
+ *p_num_prop = 0;
+ return BTA_OP_FAIL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpGetCardProperty
+**
+** Description Get Card property value by name. The input to this function is
+** property name. The output is property value and len
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpGetCardProperty(UINT8 *p_value, UINT16 *p_len, tBTA_OP_PROP *p_prop,
+ UINT8 num_prop, UINT8 *p_name)
+{
+ return bta_op_get_property_by_name(bta_op_vcard_tbl, p_name,
+ p_prop, num_prop, p_value, p_len);
+}
+
+
diff --git a/bta/op/bta_op_vnote.c b/bta/op/bta_op_vnote.c
new file mode 100644
index 0000000..ff1c015
--- /dev/null
+++ b/bta/op/bta_op_vnote.c
@@ -0,0 +1,99 @@
+/*****************************************************************************
+**
+** Name: bta_op_vnote.c
+**
+** Description: This file contains functions for parsing and building
+** vNote objects.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_op_api.h"
+#include "bta_op_fmt.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OP_VNOTE_BEGIN_LEN 26
+#define BTA_OP_VNOTE_END_LEN 11
+
+#define BTA_OP_VNOTE_MIN_LEN (BTA_OP_VNOTE_BEGIN_LEN + BTA_OP_VNOTE_END_LEN)
+
+const char bta_op_vnote_prs_begin[] = "BEGIN:VNOTE\r\n";
+
+const char bta_op_vnote_begin[] = "BEGIN:VNOTE\r\nVERSION:1.1\r\n";
+
+const char bta_op_vnote_end[] = "END:VNOTE\r\n";
+
+const tBTA_OP_PROP_TBL bta_op_vnote_tbl[] =
+{
+ {NULL, NULL, 2}, /* Number of elements in array */
+ {"BODY", NULL, 7}, /* BTA_OP_VNOTE_BODY */
+ {"X-IRMC-LUID", NULL, 14} /* BTA_OP_VNOTE_LUID */
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vnote_bld =
+{
+ bta_op_vnote_tbl,
+ BTA_OP_FMT_VNOTE11,
+ bta_op_vnote_begin,
+ bta_op_vnote_end,
+ BTA_OP_VNOTE_BEGIN_LEN,
+ BTA_OP_VNOTE_END_LEN,
+ BTA_OP_VNOTE_MIN_LEN
+};
+
+const tBTA_OP_OBJ_TBL bta_op_vnote_prs =
+{
+ bta_op_vnote_tbl,
+ BTA_OP_FMT_VNOTE11,
+ bta_op_vnote_prs_begin,
+ bta_op_vnote_end,
+ BTA_OP_VNOTE_BEGIN_LEN,
+ BTA_OP_VNOTE_END_LEN,
+ BTA_OP_VNOTE_MIN_LEN
+};
+
+/*******************************************************************************
+**
+** Function BTA_OpBuildNote
+**
+** Description Build a vNote object. The input to this function is an
+** array of vNote properties and a pointer to memory to store
+** the card. The output is a formatted vNote.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete build.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpBuildNote(UINT8 *p_note, UINT16 *p_len, tBTA_OP_PROP *p_prop,
+ UINT8 num_prop)
+{
+ return bta_op_build_obj(&bta_op_vnote_bld, p_note, p_len, p_prop, num_prop);
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpParseNote
+**
+** Description Parse a vNote object. The input to this function is a
+** pointer to vNote data. The output is an array of parsed
+** vNote properties.
+**
+**
+** Returns BTA_OP_OK if operation successful.
+** BTA_OP_FAIL if invalid property data.
+** BTA_OP_MEM if not enough memory to complete parsing.
+**
+*******************************************************************************/
+tBTA_OP_STATUS BTA_OpParseNote(tBTA_OP_PROP *p_prop, UINT8 *p_num_prop, UINT8 *p_note,
+ UINT16 len)
+{
+ return bta_op_parse_obj(&bta_op_vnote_prs, p_prop, p_num_prop, p_note, len);
+}
+
diff --git a/bta/op/bta_opc_act.c b/bta/op/bta_opc_act.c
new file mode 100644
index 0000000..cf4780d
--- /dev/null
+++ b/bta/op/bta_opc_act.c
@@ -0,0 +1,1017 @@
+/*****************************************************************************
+**
+** Name: bta_opc_act.c
+**
+** Description: This file contains the file transfer action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bd.h"
+#include "port_api.h"
+#include "obx_api.h"
+#include "goep_util.h"
+#include "sdp_api.h"
+#include "bta_fs_api.h"
+#include "bta_op_api.h"
+#include "bta_opc_int.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#include "btm_api.h"
+#include "rfcdefs.h"
+#include "utl.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+/* sdp discovery database size */
+#define BTA_OPC_DISC_SIZE 450
+
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if BTA_OPC_DEBUG == TRUE
+static char *opc_obx_evt_code(tOBX_EVENT evt_code);
+#endif
+
+static void bta_opc_sdp_cback(UINT16 status);
+
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_opc_enable
+**
+** Description Handle an api enable event. This function enables the OP
+** Client by opening an Obex/Rfcomm channel with a peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_enable(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+
+ /* store parameters */
+ p_cb->p_cback = p_data->api_enable.p_cback;
+ p_cb->sec_mask = p_data->api_enable.sec_mask;
+ p_cb->app_id = p_data->api_enable.app_id;
+ p_cb->srm = p_data->api_enable.srm;
+ p_cb->single_op = p_data->api_enable.single_op;
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* callback with enable event */
+ (*p_cb->p_cback)(BTA_OPC_ENABLE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_init_push
+**
+** Description Push an object to the OPP server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_init_push(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->status = BTA_OPC_FAIL;
+ p_cb->exch_status = BTA_OPC_OK;
+
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ p_cb->to_do = BTA_OPC_PUSH_MASK;
+ p_cb->format = p_data->api_push.format;
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len+1, p_data->api_push.p_name, p_bta_fs_cfg->max_path_len);
+ p_cb->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_init_pull
+**
+** Description Pull an object off the server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_init_pull(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->status = BTA_OPC_FAIL;
+ p_cb->exch_status = BTA_OPC_OK;
+
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len +
+ p_bta_fs_cfg->max_path_len + 2))) != NULL)
+ {
+ p_cb->p_rcv_path = p_cb->p_name + p_bta_fs_cfg->max_file_len + 1;
+ p_cb->to_do = BTA_OPC_PULL_MASK;
+ p_cb->first_get_pkt = TRUE;
+ BCM_STRNCPY_S(p_cb->p_rcv_path, p_bta_fs_cfg->max_path_len+1, p_data->api_pull.p_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_rcv_path[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_init_exch
+**
+** Description Exchange business cards with a server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_init_exch(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->status = BTA_OPC_FAIL;
+ p_cb->exch_status = BTA_OPC_OK;
+
+ /* Need room to hold the receive path, along with path and file name to push */
+ if ((p_cb->p_name =
+ (char *)GKI_getbuf((UINT16)((p_bta_fs_cfg->max_path_len + 1) * 2))) != NULL)
+ {
+ p_cb->p_rcv_path = p_cb->p_name + p_bta_fs_cfg->max_path_len + 1;
+ p_cb->to_do = BTA_OPC_PULL_MASK | BTA_OPC_PUSH_MASK;
+ p_cb->first_get_pkt = TRUE;
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len+1, p_data->api_exch.p_send, p_bta_fs_cfg->max_path_len);
+ p_cb->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ BCM_STRNCPY_S(p_cb->p_rcv_path, p_bta_fs_cfg->max_path_len+1, p_data->api_exch.p_rcv_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_rcv_path[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_trans_cmpl
+**
+** Description push/pull complete
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_trans_cmpl(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBJECT param;
+ tBTA_OPC_EVT evt = BTA_OPC_OBJECT_EVT;
+ tBTA_FS_CO_STATUS status;
+
+ if (p_data)
+ {
+ p_cb->status = bta_opc_convert_obx_to_opc_status(p_data->obx_evt.rsp_code);
+ }
+ else
+ {
+ /* some action functions send the event to SM with NULL p_data */
+ p_cb->status = BTA_OPC_FAIL;
+ }
+
+ if (p_cb->obx_oper == OPC_OP_PUSH_OBJ)
+ evt = BTA_OPC_OBJECT_PSHD_EVT;
+
+ /* rearrange the code a little bit to make sure p_cb->status is for the current op
+ * (previously, we might use the ststus from the PUSH op, if this is an exchange card) */
+ param.status = p_cb->status;
+
+ /* If exchange, and push received an error use this error */
+ if (p_cb->exch_status != BTA_OPC_OK)
+ param.status = p_cb->exch_status;
+
+ /* Notify appl the result of the pull or push */
+ param.p_name = p_cb->p_name;
+ p_cb->p_cback(evt, (tBTA_OPC *)&param);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Delete an aborted unfinished get vCard operation */
+ if (p_cb->obx_oper == OPC_OP_PULL_OBJ && p_cb->status != BTA_OPC_OK)
+ {
+ status = bta_fs_co_unlink(p_cb->p_name, p_cb->app_id);
+ APPL_TRACE_WARNING2("OPC: Remove ABORTED Get File Operation [%s], status 0x%02x",
+ p_cb->p_name, status);
+ }
+ }
+
+ utl_freebuf((void**)&p_cb->p_name);
+
+ p_cb->obx_oper = OPC_OP_NONE;
+
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_ci_write
+**
+** Description Continue with the current write operation
+** (Get File processing)
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_ci_write(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_OPC_PROGRESS param;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ p_cb->cout_active = FALSE;
+
+ /* Process write call-in event if operation is still active */
+ if (p_cb->obx_oper == OPC_OP_PULL_OBJ)
+ {
+ if (p_data->write_evt.status == BTA_FS_CO_OK)
+ {
+ param.bytes = p_obx->offset;
+ param.obj_size = p_cb->obj_size;
+ param.operation = BTA_OP_OPER_PULL;
+ p_cb->p_cback(BTA_OPC_PROGRESS_EVT, (tBTA_OPC *)&param);
+
+ /* Send another Get request if not finished */
+ if (!p_obx->final_pkt)
+ {
+ /* Free current packet and send a new request */
+ bta_opc_send_get_req(p_cb);
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ else
+ rsp_code = OBX_RSP_OK;
+ }
+
+ if (rsp_code != OBX_RSP_CONTINUE)
+ {
+ p_data->obx_evt.rsp_code = rsp_code;
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_ci_read
+**
+** Description Handles the response to a read call-out request.
+** This is called within the OBX get object request. The
+** operation has completed, send the OBX packet out.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_ci_read(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FS_CI_READ_EVT *p_revt = &p_data->read_evt;
+ tBTA_OPC_PROGRESS param;
+ BOOLEAN is_final;
+
+ p_cb->cout_active = FALSE;
+
+ /* Process read call-in event if operation is still active */
+ if (p_cb->obx_oper == OPC_OP_PUSH_OBJ)
+ {
+ if (p_revt->status != BTA_FS_CO_OK && p_revt->status != BTA_FS_CO_EOF)
+ {
+ p_data->obx_evt.rsp_code = OBX_RSP_FAILED;
+/* if abort added to OPC use -> bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, p_data); */
+ bta_opc_sm_execute(p_cb, BTA_OPC_API_CLOSE_EVT, p_data);
+ }
+ else
+ {
+ is_final = (p_revt->status == BTA_FS_CO_EOF) ? TRUE: FALSE;
+
+ /* Add the body header to the packet */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_revt->num_read, is_final);
+
+ p_cb->obx.bytes_left -= p_revt->num_read;
+ p_cb->obx.offset += p_revt->num_read;
+
+ /* Send out the data */
+ OBX_PutReq(p_cb->obx_handle, is_final, p_obx->p_pkt);
+ p_obx->p_pkt = NULL;
+ p_cb->req_pending = TRUE;
+
+ /* Give application the status */
+ param.bytes = p_revt->num_read;
+ param.obj_size = p_cb->obj_size;
+ param.operation = BTA_OP_OPER_PUSH;
+ p_cb->p_cback(BTA_OPC_PROGRESS_EVT, (tBTA_OPC *)&param);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_ci_open
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_ci_open(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FS_CI_OPEN_EVT *p_open = &p_data->open_evt;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ p_cb->cout_active = FALSE;
+
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->fd = p_open->fd;
+
+ if (p_cb->obx_oper == OPC_OP_PUSH_OBJ)
+ {
+ p_cb->obj_size = p_open->file_size;
+
+ rsp_code = bta_opc_send_put_req(p_cb, TRUE);
+ }
+ else if (p_cb->obx_oper == OPC_OP_PULL_OBJ)
+ {
+ rsp_code = OBX_RSP_OK;
+
+ /* Initiate the first OBX GET request */
+ p_obx->offset = 0;
+
+ /* Continue processing GET rsp */
+ bta_opc_cont_get_rsp(p_cb);
+ }
+ }
+ else
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else /* File could not be found */
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+
+ if (rsp_code != OBX_RSP_OK)
+ {
+ p_data->obx_evt.rsp_code = rsp_code;
+ bta_opc_sm_execute(p_cb, BTA_OPC_API_CLOSE_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_obx_conn_rsp
+**
+** Description Process the OBX connect event.
+** If OPP service, get directory listing.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_obx_conn_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_EVT *p_evt = &p_data->obx_evt;
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ p_cb->peer_mtu = p_data->obx_evt.param.conn.mtu;
+
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_OPC ,p_cb->app_id, bta_opc_cb.bd_addr);
+
+ p_cb->p_cback(BTA_OPC_OPEN_EVT, NULL);
+
+ /* start the first operation. For card exchange PUSH is done first */
+ if(p_cb->to_do & BTA_OPC_PUSH_MASK)
+ bta_opc_start_push(p_cb);
+ else
+ bta_opc_send_get_req(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_obx_put_rsp
+**
+** Description Process the OBX file put and delete file/folder events
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_obx_put_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_OPC_OBJECT param;
+
+ p_cb->req_pending = FALSE;
+ APPL_TRACE_DEBUG1("bta_opc_obx_put_rsp to_do 0x%02x",p_cb->to_do);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (p_cb->obx_oper == OPC_OP_PUSH_OBJ)
+ {
+ /* If not finished with Put, start another read */
+ if (p_evt->rsp_code == OBX_RSP_CONTINUE)
+ bta_opc_send_put_req(p_cb, FALSE);
+
+ /* Start the Pull if this is card exchange */
+ else if (p_cb->to_do & BTA_OPC_PULL_MASK)
+ {
+ /* Close the current file and initiate a pull vcard */
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* If error occurred during push save it */
+ if (p_evt->rsp_code != OBX_RSP_OK)
+ p_cb->exch_status = BTA_OPC_FAIL;
+
+ /* Notify application with status of push operation */
+ param.status = p_cb->exch_status;
+ param.p_name = p_cb->p_name;
+ p_cb->p_cback(BTA_OPC_OBJECT_PSHD_EVT, (tBTA_OPC *)&param);
+
+ /* Initiate the Pull operation */
+ bta_opc_send_get_req(p_cb);
+ }
+ else /* Finished or an error occurred */
+ {
+ p_data->obx_evt.rsp_code = p_evt->rsp_code;
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, p_data);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_obx_get_rsp
+**
+** Description Process the OBX file get and folder listing events
+** If the type header is not folder listing, then pulling a file.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_obx_get_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ BOOLEAN free_pkt = FALSE;
+
+ p_obx->final_pkt = (p_evt->rsp_code == OBX_RSP_OK) ? TRUE : FALSE;
+ p_obx->p_pkt = p_evt->p_pkt;
+ p_obx->rsp_code = p_evt->rsp_code;
+ p_cb->req_pending = FALSE;
+
+ if (p_cb->obx_oper == OPC_OP_PULL_OBJ)
+ {
+ /* Open file for writing */
+ if (p_cb->first_get_pkt == TRUE)
+ {
+ p_cb->first_get_pkt = FALSE;
+ free_pkt = bta_opc_proc_get_rsp(p_cb, p_data);
+ }
+ else /* Continuation of the object transfer */
+ bta_opc_cont_get_rsp(p_cb);
+ }
+ else
+ free_pkt = TRUE;
+
+ if (free_pkt) /* Release the OBX response packet */
+ utl_freebuf((void**)&p_obx->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_initialize
+**
+** Description Initialize the control block.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_initialize(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_FS_CO_STATUS status;
+
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Delete an aborted unfinished get vCard operation */
+ if (p_cb->obx_oper == OPC_OP_PULL_OBJ && p_cb->status != BTA_OPC_OK)
+ {
+ status = bta_fs_co_unlink(p_cb->p_name, p_cb->app_id);
+ APPL_TRACE_WARNING2("OPC: Remove ABORTED Get File Operation [%s], status 0x%02x",
+ p_cb->p_name, status);
+ }
+ }
+
+ utl_freebuf((void**)&p_cb->p_name);
+
+ /* Clean up control block */
+ p_cb->obx_oper = OPC_OP_NONE;
+ p_cb->req_pending = FALSE;
+ p_cb->sdp_pending = FALSE;
+ p_cb->to_do = 0;
+ p_cb->p_rcv_path = NULL;
+ p_cb->first_get_pkt = FALSE;
+
+ if (p_cb->disabling)
+ {
+ p_cb->disabling = FALSE;
+ bta_opc_sm_execute(p_cb, BTA_OPC_DISABLE_CMPL_EVT, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_stop_client
+**
+** Description Stop OBX client.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_stop_client(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ if (!p_cb->sdp_pending)
+ {
+// btla-specific ++
+#if defined (BTA_OPC_SENDING_ABORT) && (BTA_OPC_SENDING_ABORT == TRUE)
+ APPL_TRACE_WARNING3("bta_opc_stop_client p_cb->req_pending = %d, p_cb->sdp_pending = %d,handle = %d",
+ p_cb->req_pending, p_cb->sdp_pending,p_cb->obx_handle);
+ /* Abort an active request */
+ if (p_cb->req_pending)
+ OBX_AbortReq(p_cb->obx_handle, (BT_HDR *)NULL);
+#endif
+// btla-specific --
+ /* do not free p_cb->obx.p_pkt here, just in case cout_active.
+ * bta_opc_close_complete would handle it */
+ OBX_DisconnectReq(p_cb->obx_handle, NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_close
+**
+** Description If not waiting for a call-in function, complete the closing
+** of the channel.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->cout_active)
+ bta_opc_sm_execute(p_cb, BTA_OPC_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_start_client
+**
+** Description Start an OPP operation.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_start_client(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ tOBX_STATUS status;
+ BOOLEAN srm = p_cb->srm;
+
+ /* Allocate an OBX packet */
+ if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(OBX_HANDLE_NULL, OBX_MAX_MTU)) != NULL)
+ {
+ status = OBX_AllocSession (NULL, p_data->sdp_ok.scn, &p_data->sdp_ok.psm,
+ bta_opc_obx_cback, &p_cb->obx_handle);
+
+ /* set security level */
+ if (p_data->sdp_ok.scn)
+ {
+ BTM_SetSecurityLevel (TRUE, "BTA_OPC", BTM_SEC_SERVICE_OBEX,
+ p_cb->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, p_data->sdp_ok.scn);
+ srm = 0;
+ }
+ else
+ {
+ BTM_SetSecurityLevel (TRUE, "BTA_OPC", BTM_SEC_SERVICE_OBEX,
+ p_cb->sec_mask, p_data->sdp_ok.psm, 0, 0);
+ }
+
+ if (status == OBX_SUCCESS)
+ {
+ OBX_CreateSession (p_cb->bd_addr, OBX_MAX_MTU, srm, 0,
+ p_cb->obx_handle, p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* OBX will free the memory */
+ return;
+ }
+ }
+ else
+ {
+ p_data->obx_evt.rsp_code = OBX_RSP_FAILED;
+ bta_opc_sm_execute(p_cb, BTA_OPC_CLOSE_CMPL_EVT, p_data);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_free_db
+**
+** Description Free buffer used for service discovery database.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_free_db(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ utl_freebuf((void**)&p_cb->p_db);
+ p_cb->sdp_pending = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_ignore_obx
+**
+** Description Free OBX packet for ignored OBX events.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_ignore_obx(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_find_service
+**
+** Description Perform service discovery to find the OPP service on the
+** peer device.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_find_service(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tSDP_UUID uuid_list;
+ UINT16 attr_list[3];
+
+ if (!p_cb->to_do)
+ return;
+
+ bdcpy(p_cb->bd_addr, p_data->api_push.bd_addr);
+ if ((p_cb->p_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_OPC_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_OBX_OVR_L2CAP_PSM;
+
+ uuid_list.len = LEN_UUID_16;
+ uuid_list.uu.uuid16 = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
+ p_cb->sdp_pending = TRUE;
+ SDP_InitDiscoveryDb(p_cb->p_db, BTA_OPC_DISC_SIZE, 1, &uuid_list, 3, attr_list);
+ if(!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db, bta_opc_sdp_cback))
+ {
+ bta_opc_sm_execute(p_cb, BTA_OPC_SDP_FAIL_EVT, (tBTA_OPC_DATA *)NULL);
+ }
+ }
+ else
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_close_complete
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_close_complete(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->cout_active = FALSE;
+ bta_opc_initialize(p_cb, p_data);
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_OPC ,p_cb->app_id, bta_opc_cb.bd_addr);
+
+ p_cb->p_cback(BTA_OPC_CLOSE_EVT, (tBTA_OPC *)&p_cb->status);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_set_disable
+**
+** Description Sets flag to disable.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_set_disable(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ p_cb->disabling = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_chk_close
+**
+** Description Check if we need to stop the client now.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_chk_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ if (p_cb->single_op)
+ {
+ bta_opc_sm_execute(p_cb, BTA_OPC_API_CLOSE_EVT, (tBTA_OPC_DATA *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_do_pull
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_do_pull(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1("bta_opc_do_pull to_do 0x%02x",p_cb->to_do);
+ bta_opc_send_get_req(p_cb);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_do_push
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_do_push(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ APPL_TRACE_DEBUG1("bta_opc_do_push to_do 0x%02x",p_cb->to_do);
+ bta_opc_start_push(p_cb);
+}
+
+/*****************************************************************************
+** Callback Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_opc_obx_cback
+**
+** Description OBX callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event, UINT8 rsp_code,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_OPC_OBX_EVT *p_obx_msg;
+ UINT16 event = 0;
+
+#if BTA_OPC_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("OBX Event Callback: obx_event [%s]", opc_obx_evt_code(obx_event));
+#endif
+
+ switch(obx_event)
+ {
+ case OBX_CONNECT_RSP_EVT:
+ if (rsp_code == OBX_RSP_OK)
+ {
+ event = BTA_OPC_OBX_CONN_RSP_EVT;
+ }
+ else /* Obex will disconnect underneath BTA */
+ {
+ APPL_TRACE_WARNING1("OPC_CBACK: Bad connect response 0x%02x", rsp_code);
+ if (p_pkt)
+ GKI_freebuf(p_pkt);
+ return;
+ }
+ break;
+ case OBX_PUT_RSP_EVT:
+ event = BTA_OPC_OBX_PUT_RSP_EVT;
+ break;
+ case OBX_GET_RSP_EVT:
+ event = BTA_OPC_OBX_GET_RSP_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_OPC_OBX_CLOSE_EVT;
+ break;
+ case OBX_PASSWORD_EVT:
+ event = BTA_OPC_OBX_PASSWORD_EVT;
+ break;
+
+ default:
+/* case OBX_ABORT_RSP_EVT: */
+/* case OBX_DISCONNECT_RSP_EVT: Handled when OBX_CLOSE_IND_EVT arrives */
+ if (p_pkt)
+ GKI_freebuf(p_pkt);
+ return;
+ }
+
+ /* send event to BTA, if any */
+ if ((p_obx_msg = (tBTA_OPC_OBX_EVT *) GKI_getbuf(sizeof(tBTA_OPC_OBX_EVT))) != NULL)
+ {
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->rsp_code = rsp_code;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+
+/******************************************************************************
+**
+** Function bta_opc_sdp_cback
+**
+** Description This is the SDP callback function used by OPC.
+** 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 Nothing.
+**
+******************************************************************************/
+static void bta_opc_sdp_cback(UINT16 status)
+{
+ tBTA_OPC_SDP_OK_EVT *p_buf;
+ tSDP_DISC_REC *p_rec = NULL;
+ tSDP_PROTOCOL_ELEM pe;
+ UINT8 scn = 0;
+ BOOLEAN found = FALSE;
+ UINT16 version = GOEP_LEGACY_VERSION;
+ UINT16 psm = 0;
+ tSDP_DISC_ATTR *p_attr;
+
+ APPL_TRACE_DEBUG1("bta_opc_sdp_cback status:%d", status);
+
+ if ( (status == SDP_SUCCESS) || (status == SDP_DB_FULL) )
+ {
+ status = SDP_SUCCESS;
+ /* loop through all records we found */
+ do
+ {
+ /* get next record; if none found, we're done */
+ if ((p_rec = SDP_FindServiceInDb(bta_opc_cb.p_db,
+ UUID_SERVCLASS_OBEX_OBJECT_PUSH, p_rec)) == NULL)
+ break;
+
+ /* this is an optional attribute */
+ SDP_FindProfileVersionInRec (p_rec, UUID_SERVCLASS_OBEX_OBJECT_PUSH, &version);
+
+ /* get psm from proto desc list alternative; if not found, go to next record */
+ if ((p_attr = SDP_FindAttributeInRec(p_rec,
+ ATTR_ID_OBX_OVR_L2CAP_PSM)) != NULL)
+ {
+ psm = p_attr->attr_value.v.u16;
+ if ((SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2) && L2C_IS_VALID_PSM(psm))
+ {
+ found = TRUE;
+ if (version == GOEP_LEGACY_VERSION)
+ {
+ APPL_TRACE_ERROR0("Lacking mandatory attribute/version");
+ version = GOEP_ENHANCED_VERSION;
+ }
+ break;
+ }
+ }
+
+ /* If no OBEX over L2CAP look for RFCOMM SCN */
+ if (!found)
+ {
+ /* get scn from proto desc list; if not found, go to next record */
+ if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+ {
+ scn = (UINT8) pe.params[0];
+
+ /* we've got everything, we're done */
+ found = TRUE;
+ break;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ } while (TRUE);
+ }
+
+ /* send result in event back to BTA */
+ if ((p_buf = (tBTA_OPC_SDP_OK_EVT *) GKI_getbuf(sizeof(tBTA_OPC_SDP_OK_EVT))) != NULL)
+ {
+ if ((status == SDP_SUCCESS) && (found == TRUE))
+ {
+ p_buf->hdr.event = BTA_OPC_SDP_OK_EVT;
+ p_buf->scn = scn;
+ p_buf->psm = psm;
+ p_buf->version = version;
+ }
+ else
+ p_buf->hdr.event = BTA_OPC_SDP_FAIL_EVT;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*****************************************************************************
+** Local OPP Event Processing Functions
+*****************************************************************************/
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_OPC_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function opc_obx_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *opc_obx_evt_code(tOBX_EVENT evt_code)
+{
+ switch(evt_code)
+ {
+ case OBX_CONNECT_RSP_EVT:
+ return "OBX_CONNECT_RSP_EVT";
+ case OBX_DISCONNECT_RSP_EVT:
+ return "OBX_DISCONNECT_RSP_EVT";
+ case OBX_PUT_RSP_EVT:
+ return "OBX_PUT_RSP_EVT";
+ case OBX_GET_RSP_EVT:
+ return "OBX_GET_RSP_EVT";
+ case OBX_SETPATH_RSP_EVT:
+ return "OBX_SETPATH_RSP_EVT";
+ case OBX_ABORT_RSP_EVT:
+ return "OBX_ABORT_RSP_EVT";
+ case OBX_CLOSE_IND_EVT:
+ return "OBX_CLOSE_IND_EVT";
+ case OBX_TIMEOUT_EVT:
+ return "OBX_TIMEOUT_EVT";
+ case OBX_PASSWORD_EVT:
+ return "OBX_PASSWORD_EVT";
+ default:
+ return "unknown OBX event code";
+ }
+}
+#endif /* Debug Functions */
diff --git a/bta/op/bta_opc_api.c b/bta/op/bta_opc_api.c
new file mode 100644
index 0000000..4440b1c
--- /dev/null
+++ b/bta/op/bta_opc_api.c
@@ -0,0 +1,214 @@
+/*****************************************************************************
+**
+** Name: bta_opc_api.c
+**
+** Description: This is the implementation of the API for the object
+** push client subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2003 - 2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_fs_api.h"
+#include "bta_op_api.h"
+#include "bta_opc_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_opc_reg =
+{
+ bta_opc_hdl_event,
+ BTA_OpcDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_OpcEnable
+**
+** Description Enable the object push client. This function must be
+** called before any other functions in the DG API are called.
+** When the enable operation is complete the callback function
+** will be called with a BTA_OPC_ENABLE_EVT.
+**
+** If single_op is FALSE, the connection stays open after
+** the operation finishes (until BTA_OpcClose is called).
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcEnable(tBTA_SEC sec_mask, tBTA_OPC_CBACK *p_cback,
+ BOOLEAN single_op, BOOLEAN srm, UINT8 app_id)
+{
+ tBTA_OPC_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_OPC, &bta_opc_reg);
+ GKI_sched_unlock();
+
+ /* initialize control block */
+ memset(&bta_opc_cb, 0, sizeof(tBTA_OPC_CB));
+
+ if ((p_buf = (tBTA_OPC_API_ENABLE *) GKI_getbuf(sizeof(tBTA_OPC_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_OPC_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->sec_mask = sec_mask;
+ p_buf->single_op = single_op;
+ p_buf->srm = srm;
+ p_buf->app_id = app_id;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcDisable
+**
+** Description Disable the object push client. If the client is currently
+** connected to a peer device the connection will be closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_OPC);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_OPC_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcPush
+**
+** Description Push an object to a peer device. p_name must point to
+** a fully qualified path and file name.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcPush(BD_ADDR bd_addr, tBTA_OP_FMT format, char *p_name)
+{
+ tBTA_OPC_DATA *p_msg;
+
+ if ((p_msg = (tBTA_OPC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_OPC_DATA) +
+ p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ p_msg->api_push.p_name = (char *)(p_msg + 1);
+ BCM_STRNCPY_S(p_msg->api_push.p_name, p_bta_fs_cfg->max_path_len+1, p_name, p_bta_fs_cfg->max_path_len);
+ p_msg->api_push.p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ p_msg->hdr.event = BTA_OPC_API_PUSH_EVT;
+ bdcpy(p_msg->api_push.bd_addr, bd_addr);
+ p_msg->api_push.format = format;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcPullCard
+**
+** Description Pull default card from peer. p_path must point to a fully
+** qualified path specifying where to store the pulled card.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcPullCard(BD_ADDR bd_addr, char *p_path)
+{
+ tBTA_OPC_DATA *p_msg;
+ tBTA_OPC_API_PULL *p_pull;
+
+ if ((p_msg = (tBTA_OPC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_OPC_DATA) +
+ (p_bta_fs_cfg->max_path_len + 1)))) != NULL)
+ {
+ p_pull = &p_msg->api_pull;
+ p_pull->p_path = (char *)(p_msg + 1);
+ BCM_STRNCPY_S(p_pull->p_path, p_bta_fs_cfg->max_path_len+1, p_path, p_bta_fs_cfg->max_path_len);
+ p_pull->p_path[p_bta_fs_cfg->max_path_len] = '\0';
+ bdcpy(p_pull->bd_addr, bd_addr);
+ p_pull->hdr.event = BTA_OPC_API_PULL_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcExchCard
+**
+** Description Exchange business cards with a peer device. p_send points to
+** a fully qualified path and file name of vcard to push.
+** p_recv_path points to a fully qualified path specifying
+** where to store the pulled card.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcExchCard(BD_ADDR bd_addr, char *p_send, char *p_recv_path)
+{
+ tBTA_OPC_DATA *p_msg;
+ tBTA_OPC_API_EXCH *p_exch;
+
+ if(!p_send || !p_recv_path)
+ return;
+
+ if ((p_msg = (tBTA_OPC_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_OPC_DATA) +
+ (p_bta_fs_cfg->max_path_len + 1) * 2))) != NULL)
+ {
+ p_exch = &p_msg->api_exch;
+ p_exch->p_send = (char *)(p_msg + 1);
+ p_exch->p_rcv_path = (char *)(p_exch->p_send + p_bta_fs_cfg->max_path_len + 1);
+ BCM_STRNCPY_S(p_exch->p_send, p_bta_fs_cfg->max_path_len+1, p_send, p_bta_fs_cfg->max_path_len);
+ p_exch->p_send[p_bta_fs_cfg->max_path_len] = '\0';
+ BCM_STRNCPY_S(p_exch->p_rcv_path, p_bta_fs_cfg->max_path_len+1, p_recv_path, p_bta_fs_cfg->max_path_len);
+ p_exch->p_rcv_path[p_bta_fs_cfg->max_path_len] = '\0';
+ bdcpy(p_exch->bd_addr, bd_addr);
+ p_exch->hdr.event = BTA_OPC_API_EXCH_EVT;
+ bta_sys_sendmsg(p_msg);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpcClose
+**
+** Description Close the current connection. This function is called if
+** the phone wishes to close the connection before the object
+** push is completed. In a typical connection this function
+** does not need to be called; the connection will be closed
+** automatically when the object push is complete.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpcClose(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_OPC_API_CLOSE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
diff --git a/bta/op/bta_opc_int.h b/bta/op/bta_opc_int.h
new file mode 100644
index 0000000..e26d2b5
--- /dev/null
+++ b/bta/op/bta_opc_int.h
@@ -0,0 +1,257 @@
+/*****************************************************************************
+**
+** Name: bta_opc_int.h
+**
+** Description: This is the private header file for the Object Push
+** Client (OPC).
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_OPC_INT_H
+#define BTA_OPC_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_op_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+
+#define OPC_DEF_NAME "default_opc.vcf"
+
+/* if the pulled vCard does not have a Name Header associated with it,
+ * this is the default name used to received the file.
+ * Please make sure that this is of different file name than the local
+ * default vCard file name */
+#ifndef OPC_DEF_RCV_NAME
+#define OPC_DEF_RCV_NAME "opc_def_rcv.vcf"
+#endif
+
+/* OPC Active opp obex operation (Valid in connected state) */
+#define OPC_OP_NONE 0
+#define OPC_OP_PULL_OBJ 1
+#define OPC_OP_PUSH_OBJ 2
+
+/* Constants used for "to_do" list */
+#define BTA_OPC_PUSH_MASK 0x01
+#define BTA_OPC_PULL_MASK 0x02
+
+/* state machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_OPC_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_OPC),
+ BTA_OPC_API_DISABLE_EVT,
+ BTA_OPC_API_CLOSE_EVT, /* Close connection event */
+ BTA_OPC_API_PUSH_EVT, /* Push Object request */
+ BTA_OPC_API_PULL_EVT, /* Pull Object request */
+ BTA_OPC_API_EXCH_EVT, /* Exchange business Cards */
+ BTA_OPC_SDP_OK_EVT, /* Service search was successful */
+ BTA_OPC_SDP_FAIL_EVT, /* Service search failed */
+ BTA_OPC_CI_WRITE_EVT, /* Call-in response to Write request */
+ BTA_OPC_CI_READ_EVT, /* Call-in response to Read request */
+ BTA_OPC_CI_OPEN_EVT, /* Call-in response to File Open request */
+ BTA_OPC_OBX_CONN_RSP_EVT, /* OBX Channel Connect Request */
+ BTA_OPC_OBX_PASSWORD_EVT, /* OBX password requested */
+ BTA_OPC_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_OPC_OBX_PUT_RSP_EVT, /* Write file data or delete */
+ BTA_OPC_OBX_GET_RSP_EVT, /* Read file data or folder listing */
+ BTA_OPC_OBX_CMPL_EVT, /* operation has completed */
+ BTA_OPC_CLOSE_CMPL_EVT, /* Finish the closing of the channel */
+ BTA_OPC_DISABLE_CMPL_EVT /* Transition to disabled state */
+};
+
+typedef UINT16 tBTA_OPC_INT_EVT;
+
+typedef UINT8 tBTA_OPC_STATE;
+
+/* data type for BTA_OPC_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_OPC_CBACK *p_cback;
+ UINT8 sec_mask;
+ BOOLEAN single_op;
+ BOOLEAN srm;
+ UINT8 app_id;
+} tBTA_OPC_API_ENABLE;
+
+/* data type for BTA_OPC_API_PUSH_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ char *p_name;
+ tBTA_OP_FMT format;
+} tBTA_OPC_API_PUSH;
+
+/* data type for BTA_OPC_API_PULL_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ char *p_path;
+} tBTA_OPC_API_PULL;
+
+/* data type for BTA_OPC_API_EXCH_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR bd_addr;
+ char *p_send;
+ char *p_rcv_path;
+} tBTA_OPC_API_EXCH;
+
+/* data type for BTA_OPC_SDP_OK_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 scn;
+ UINT16 psm;
+ UINT16 version;
+} tBTA_OPC_SDP_OK_EVT;
+
+/* data type for all obex events
+ hdr.event contains the OPC event
+*/
+typedef struct
+{
+ BT_HDR hdr;
+ tOBX_HANDLE handle;
+ tOBX_EVT_PARAM param;
+ BT_HDR *p_pkt;
+ tOBX_EVENT obx_event;
+ UINT8 rsp_code;
+} tBTA_OPC_OBX_EVT;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_OPC_API_ENABLE api_enable;
+ tBTA_OPC_API_PUSH api_push;
+ tBTA_OPC_API_PULL api_pull;
+ tBTA_OPC_API_EXCH api_exch;
+ tBTA_OPC_SDP_OK_EVT sdp_ok;
+ tBTA_OPC_OBX_EVT obx_evt;
+ tBTA_FS_CI_OPEN_EVT open_evt;
+ tBTA_FS_CI_READ_EVT read_evt;
+ tBTA_FS_CI_WRITE_EVT write_evt;
+} tBTA_OPC_DATA;
+
+
+/* OBX Response Packet Structure - Holds current command/response packet info */
+typedef struct
+{
+ BT_HDR *p_pkt; /* (Get/Put) Holds the current OBX header for Put or Get */
+ UINT8 *p_start; /* (Get/Put) Start of the Body of the packet */
+ UINT16 offset; /* (Get/Put) Contains the current offset into the Body (p_start) */
+ UINT16 bytes_left; /* (Get/Put) Holds bytes available leop in Obx packet */
+ BOOLEAN final_pkt; /* (Get) Holds the final bit of the Put packet */
+ UINT8 rsp_code;
+} tBTA_OPC_OBX_PKT;
+
+/* Power management state for OPC */
+#define BTA_OPC_PM_BUSY 0
+#define BTA_OPC_PM_IDLE 1
+
+/* OPC control block */
+typedef struct
+{
+ tBTA_OPC_CBACK *p_cback; /* pointer to application callback function */
+ char *p_name; /* Holds the local path and file name of pushed item */
+ char *p_rcv_path; /* Holds the local path and file name of received item (card exch only) */
+ tSDP_DISCOVERY_DB *p_db; /* pointer to discovery database */
+ tBTA_OPC_OBX_PKT obx; /* Holds the current OBX packet information */
+ int fd; /* File Descriptor of opened file */
+ UINT32 obj_size; /* (Push/Pull) file length */
+ tOBX_HANDLE obx_handle;
+ UINT16 peer_mtu;
+ BD_ADDR bd_addr;
+ BOOLEAN single_op; /* if TRUE, close OBX connection when OP finishes */
+ UINT8 sec_mask;
+ tBTA_OPC_STATE state; /* state machine state */
+ tBTA_OP_FMT format;
+ UINT8 obx_oper; /* current active OBX operation PUT FILE or GET FILE */
+ UINT8 to_do; /* actions to be done (push,pull) */
+ UINT8 app_id;
+ tBTA_OPC_STATUS status;
+ tBTA_OPC_STATUS exch_status;
+ BOOLEAN first_get_pkt; /* TRUE if retrieving the first packet of GET object */
+ BOOLEAN cout_active; /* TRUE if call-out is currently active */
+ BOOLEAN req_pending; /* TRUE if an obx request to peer is in progress */
+ BOOLEAN disabling; /* TRUE if an disabling client */
+ BOOLEAN sdp_pending; /* TRUE when waiting for SDP to complete */
+ BOOLEAN srm; /* TRUE, to use SIngle Response Mode */
+ UINT8 pm_state;
+} tBTA_OPC_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* OPC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_OPC_CB bta_opc_cb;
+#else
+extern tBTA_OPC_CB *bta_opc_cb_ptr;
+#define bta_opc_cb (*bta_opc_cb_ptr)
+#endif
+
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern BOOLEAN bta_opc_hdl_event(BT_HDR *p_msg);
+extern void bta_opc_sm_execute(tBTA_OPC_CB *p_cb, UINT16 event,
+ tBTA_OPC_DATA *p_data);
+extern void bta_opc_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ UINT8 rsp_code, tOBX_EVT_PARAM param,
+ BT_HDR *p_pkt);
+
+/* action functions */
+extern void bta_opc_init_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_init_push(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_init_pull(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_init_exch(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_send_authrsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_ci_write(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_ci_read(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_ci_open(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_obx_conn_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_obx_put_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_obx_get_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_initialize(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_trans_cmpl(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_stop_client(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_start_client(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_free_db(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_ignore_obx(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_find_service(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_close_complete(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_set_disable(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_chk_close(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_do_pull(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_do_push(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_enable(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+
+/* miscellaneous functions */
+extern UINT8 bta_opc_send_get_req(tBTA_OPC_CB *p_cb);
+extern BOOLEAN bta_opc_proc_get_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+extern void bta_opc_cont_get_rsp(tBTA_OPC_CB *p_cb);
+extern UINT8 bta_opc_send_put_req(tBTA_OPC_CB *p_cb, BOOLEAN first_pkt);
+extern void bta_opc_start_push(tBTA_OPC_CB *p_cb);
+extern void bta_opc_listing_err(BT_HDR **p_pkt, tBTA_OPC_STATUS status);
+
+extern tBTA_OPC_STATUS bta_opc_convert_obx_to_opc_status(tOBX_STATUS obx_status);
+
+#endif /* BTA_OPC_INT_H */
diff --git a/bta/op/bta_opc_main.c b/bta/op/bta_opc_main.c
new file mode 100644
index 0000000..cf76143
--- /dev/null
+++ b/bta/op/bta_opc_main.c
@@ -0,0 +1,425 @@
+/*****************************************************************************
+**
+** Name: bta_opc_main.c
+**
+** Description: This file contains the file transfer client main functions
+** and state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#include <string.h>
+
+#include "bta_opc_int.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+ BTA_OPC_DISABLED_ST = 0, /* Disabled */
+ BTA_OPC_IDLE_ST, /* Idle */
+ BTA_OPC_W4_CONN_ST, /* Waiting for an Obex connect response */
+ BTA_OPC_CONN_ST, /* Connected - OPP Session is active */
+ BTA_OPC_CLOSING_ST /* Closing is in progress */
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_OPC_START_CLIENT,
+ BTA_OPC_STOP_CLIENT,
+ BTA_OPC_INIT_PULL,
+ BTA_OPC_INIT_PUSH,
+ BTA_OPC_INIT_EXCH,
+ BTA_OPC_CI_WRITE,
+ BTA_OPC_CI_READ,
+ BTA_OPC_CI_OPEN,
+ BTA_OPC_OBX_CONN_RSP,
+ BTA_OPC_CLOSE,
+ BTA_OPC_OBX_PUT_RSP,
+ BTA_OPC_OBX_GET_RSP,
+ BTA_OPC_TRANS_CMPL,
+ BTA_OPC_FREE_DB,
+ BTA_OPC_IGNORE_OBX,
+ BTA_OPC_FIND_SERVICE,
+ BTA_OPC_INITIALIZE,
+ BTA_OPC_CLOSE_COMPLETE,
+ BTA_OPC_SET_DISABLE,
+ BTA_OPC_CHK_CLOSE,
+ BTA_OPC_DO_PUSH,
+ BTA_OPC_DO_PULL,
+ BTA_OPC_ENABLE,
+ BTA_OPC_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_OPC_ACTION)(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data);
+
+/* action function list */
+const tBTA_OPC_ACTION bta_opc_action[] =
+{
+ bta_opc_start_client,
+ bta_opc_stop_client,
+ bta_opc_init_pull,
+ bta_opc_init_push,
+ bta_opc_init_exch,
+ bta_opc_ci_write,
+ bta_opc_ci_read,
+ bta_opc_ci_open,
+ bta_opc_obx_conn_rsp,
+ bta_opc_close,
+ bta_opc_obx_put_rsp,
+ bta_opc_obx_get_rsp,
+ bta_opc_trans_cmpl,
+ bta_opc_free_db,
+ bta_opc_ignore_obx,
+ bta_opc_find_service,
+ bta_opc_initialize,
+ bta_opc_close_complete,
+ bta_opc_set_disable,
+ bta_opc_chk_close,
+ bta_opc_do_push,
+ bta_opc_do_pull,
+ bta_opc_enable
+};
+
+
+/* state table information */
+#define BTA_OPC_ACTIONS 2 /* number of actions */
+#define BTA_OPC_NEXT_STATE 2 /* position of next state */
+#define BTA_OPC_NUM_COLS 3 /* number of columns in state tables */
+
+/* state table for disabled state (enable is handled*/
+static const UINT8 bta_opc_st_disabled[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_ENABLE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* state table for idle state */
+static const UINT8 bta_opc_st_idle[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_INITIALIZE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_INIT_PUSH, BTA_OPC_FIND_SERVICE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_INIT_PULL, BTA_OPC_FIND_SERVICE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_INIT_EXCH, BTA_OPC_FIND_SERVICE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_SDP_OK_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_SDP_FAIL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_WRITE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_READ_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_OPEN_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_CONN_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_PASSWORD_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_CLOSE_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_PUT_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_GET_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CLOSE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_DISABLE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* state table for wait for authentication response state */
+static const UINT8 bta_opc_st_w4_conn[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_SET_DISABLE, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_STOP_CLIENT, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_SDP_OK_EVT */ {BTA_OPC_FREE_DB, BTA_OPC_START_CLIENT, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_SDP_FAIL_EVT */ {BTA_OPC_FREE_DB, BTA_OPC_CLOSE_COMPLETE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_WRITE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_CI_READ_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_CI_OPEN_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_OBX_CONN_RSP_EVT */ {BTA_OPC_OBX_CONN_RSP, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_PASSWORD_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_STOP_CLIENT, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_OBX_CLOSE_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_PUT_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_OBX_GET_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_W4_CONN_ST},
+/* BTA_OPC_OBX_CMPL_EVT */ {BTA_OPC_TRANS_CMPL, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_CLOSE_CMPL_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_DISABLE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_opc_st_connected[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_SET_DISABLE, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_STOP_CLIENT, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_INIT_PUSH, BTA_OPC_DO_PUSH, BTA_OPC_CONN_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_INIT_PULL, BTA_OPC_DO_PULL, BTA_OPC_CONN_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_INIT_EXCH, BTA_OPC_DO_PUSH, BTA_OPC_CONN_ST},
+/* BTA_OPC_SDP_OK_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_SDP_FAIL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_CI_WRITE_EVT */ {BTA_OPC_CI_WRITE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_CI_READ_EVT */ {BTA_OPC_CI_READ, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_CI_OPEN_EVT */ {BTA_OPC_CI_OPEN, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_CONN_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_PASSWORD_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_CLOSE_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_PUT_RSP_EVT */ {BTA_OPC_OBX_PUT_RSP, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_GET_RSP_EVT */ {BTA_OPC_OBX_GET_RSP, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_OBX_CMPL_EVT */ {BTA_OPC_TRANS_CMPL, BTA_OPC_CHK_CLOSE, BTA_OPC_CONN_ST},
+/* BTA_OPC_CLOSE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CONN_ST},
+/* BTA_OPC_DISABLE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_opc_st_closing[][BTA_OPC_NUM_COLS] =
+{
+/* Event Action 1 Action 2 Next state */
+/* BTA_OPC_API_ENABLE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_DISABLE_EVT */ {BTA_OPC_SET_DISABLE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_CLOSE_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_PUSH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_PULL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_API_EXCH_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_SDP_OK_EVT */ {BTA_OPC_FREE_DB, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_SDP_FAIL_EVT */ {BTA_OPC_FREE_DB, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_CI_WRITE_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_READ_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_CI_OPEN_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_OBX_CONN_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_STOP_CLIENT, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_PASSWORD_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_CLOSE_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_CLOSE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_PUT_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_GET_RSP_EVT */ {BTA_OPC_IGNORE_OBX, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_OBX_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_CLOSING_ST},
+/* BTA_OPC_CLOSE_CMPL_EVT */ {BTA_OPC_CLOSE_COMPLETE,BTA_OPC_IGNORE, BTA_OPC_IDLE_ST},
+/* BTA_OPC_DISABLE_CMPL_EVT */ {BTA_OPC_IGNORE, BTA_OPC_IGNORE, BTA_OPC_DISABLED_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_OPC_ST_TBL)[BTA_OPC_NUM_COLS];
+
+/* state table */
+const tBTA_OPC_ST_TBL bta_opc_st_tbl[] =
+{
+ bta_opc_st_disabled,
+ bta_opc_st_idle,
+ bta_opc_st_w4_conn,
+ bta_opc_st_connected,
+ bta_opc_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* OPC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_OPC_CB bta_opc_cb;
+#endif
+
+#if BTA_OPC_DEBUG == TRUE
+static char *opc_evt_code(tBTA_OPC_INT_EVT evt_code);
+static char *opc_state_code(tBTA_OPC_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_opc_sm_execute
+**
+** Description State machine event handling function for OPC
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_sm_execute(tBTA_OPC_CB *p_cb, UINT16 event, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+ /* look up the state table for the current state */
+ state_table = bta_opc_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_OPC_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_OPC_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_OPC_IGNORE)
+ {
+ (*bta_opc_action[action])(p_cb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_hdl_event
+**
+** Description File transfer server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_opc_hdl_event(BT_HDR *p_msg)
+{
+ tBTA_OPC_CB *p_cb = &bta_opc_cb;
+
+#if BTA_OPC_DEBUG == TRUE
+ tBTA_OPC_STATE in_state = p_cb->state;
+ APPL_TRACE_DEBUG3("OPC Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ opc_state_code(in_state),
+ opc_evt_code(p_msg->event));
+#endif
+
+ bta_opc_sm_execute(p_cb, p_msg->event, (tBTA_OPC_DATA *) p_msg);
+
+ if ( p_cb->state == BTA_OPC_CONN_ST )
+ {
+ if (( p_cb->pm_state == BTA_OPC_PM_IDLE )
+ &&( p_cb->obx_oper != OPC_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA OPC informs DM/PM busy state");
+ bta_sys_busy( BTA_ID_OPC, p_cb->app_id, p_cb->bd_addr );
+ p_cb->pm_state = BTA_OPC_PM_BUSY;
+ }
+ else if (( p_cb->pm_state == BTA_OPC_PM_BUSY )
+ &&( p_cb->obx_oper == OPC_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA OPC informs DM/PM idle state");
+ bta_sys_idle( BTA_ID_OPC ,p_cb->app_id, p_cb->bd_addr);
+ p_cb->pm_state = BTA_OPC_PM_IDLE;
+ }
+ }
+ else if ( p_cb->state == BTA_OPC_IDLE_ST )
+ {
+ /* initialize power management state */
+ p_cb->pm_state = BTA_OPC_PM_BUSY;
+ }
+
+#if BTA_OPC_DEBUG == TRUE
+ if (in_state != p_cb->state)
+ {
+ APPL_TRACE_DEBUG3("OPC State Change: [%s] -> [%s] after Event [%s]",
+ opc_state_code(in_state),
+ opc_state_code(p_cb->state),
+ opc_evt_code(p_msg->event));
+ }
+#endif
+
+ return (TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_OPC_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function opc_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *opc_evt_code(tBTA_OPC_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_OPC_API_ENABLE_EVT:
+ return "BTA_OPC_API_ENABLE_EVT";
+ case BTA_OPC_API_DISABLE_EVT:
+ return "BTA_OPC_API_DISABLE_EVT";
+ case BTA_OPC_API_CLOSE_EVT:
+ return "BTA_OPC_API_CLOSE_EVT";
+ case BTA_OPC_API_PUSH_EVT:
+ return "BTA_OPC_API_PUSH_EVT";
+ case BTA_OPC_API_PULL_EVT:
+ return "BTA_OPC_API_PULL_EVT";
+ case BTA_OPC_API_EXCH_EVT:
+ return "BTA_OPC_API_EXCH_EVT";
+ case BTA_OPC_SDP_OK_EVT:
+ return "BTA_OPC_SDP_OK_EVT";
+ case BTA_OPC_SDP_FAIL_EVT:
+ return "BTA_OPC_SDP_FAIL_EVT";
+ case BTA_OPC_CI_WRITE_EVT:
+ return "BTA_OPC_CI_WRITE_EVT";
+ case BTA_OPC_CI_READ_EVT:
+ return "BTA_OPC_CI_READ_EVT";
+ case BTA_OPC_CI_OPEN_EVT:
+ return "BTA_OPC_CI_OPEN_EVT";
+ case BTA_OPC_OBX_CONN_RSP_EVT:
+ return "BTA_OPC_OBX_CONN_RSP_EVT";
+ case BTA_OPC_OBX_PASSWORD_EVT:
+ return "BTA_OPC_OBX_PASSWORD_EVT";
+ case BTA_OPC_OBX_CLOSE_EVT:
+ return "BTA_OPC_OBX_CLOSE_EVT";
+ case BTA_OPC_OBX_PUT_RSP_EVT:
+ return "BTA_OPC_OBX_PUT_RSP_EVT";
+ case BTA_OPC_OBX_GET_RSP_EVT:
+ return "BTA_OPC_OBX_GET_RSP_EVT";
+ case BTA_OPC_OBX_CMPL_EVT:
+ return "BTA_OPC_OBX_CMPL_EVT";
+ case BTA_OPC_CLOSE_CMPL_EVT:
+ return "BTA_OPC_CLOSE_CMPL_EVT";
+ case BTA_OPC_DISABLE_CMPL_EVT:
+ return "BTA_OPC_DISABLE_CMPL_EVT";
+ default:
+ return "unknown OPC event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function opc_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *opc_state_code(tBTA_OPC_STATE state_code)
+{
+ switch(state_code)
+ {
+ case BTA_OPC_DISABLED_ST:
+ return "BTA_OPC_DISABLED_ST";
+ case BTA_OPC_IDLE_ST:
+ return "BTA_OPC_IDLE_ST";
+ case BTA_OPC_W4_CONN_ST:
+ return "BTA_OPC_W4_CONN_ST";
+ case BTA_OPC_CONN_ST:
+ return "BTA_OPC_CONN_ST";
+ case BTA_OPC_CLOSING_ST:
+ return "BTA_OPC_CLOSING_ST";
+ default:
+ return "unknown OPC state code";
+ }
+}
+
+#endif /* Debug Functions */
diff --git a/bta/op/bta_opc_utils.c b/bta/op/bta_opc_utils.c
new file mode 100644
index 0000000..82e626c
--- /dev/null
+++ b/bta/op/bta_opc_utils.c
@@ -0,0 +1,322 @@
+/*****************************************************************************
+**
+** Name: bta_opc_utils.c
+**
+** Description: This file implements object store functions for the
+** file transfer server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "bta_opc_int.h"
+#include "bta_fs_api.h"
+#include "bta_fs_co.h"
+#include "gki.h"
+#include "utl.h"
+
+/*******************************************************************************
+** Constants
+*******************************************************************************/
+
+/*******************************************************************************
+** Local Function Prototypes
+*******************************************************************************/
+
+/*******************************************************************************
+* Macros for OPC
+*******************************************************************************/
+
+/*******************************************************************************
+* Exported Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_opc_send_get_req
+**
+** Description Processes a Get File Operation.
+**
+** Parameters p_cb - Pointer to the OPC control block
+**
+** Returns (UINT8) OBX response code
+**
+*******************************************************************************/
+UINT8 bta_opc_send_get_req(tBTA_OPC_CB *p_cb)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+
+ utl_freebuf((void**)&p_obx->p_pkt);
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, p_cb->peer_mtu)) != NULL)
+ {
+ /* If first request add the Type Header to the request */
+ if (p_cb->first_get_pkt == TRUE)
+ {
+ p_cb->obx_oper = OPC_OP_PULL_OBJ;
+ p_cb->to_do &= ~BTA_OPC_PULL_MASK;
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vcard");
+ }
+
+ if ((OBX_GetReq(p_cb->obx_handle, TRUE, p_obx->p_pkt)) == OBX_SUCCESS)
+ {
+ rsp_code = OBX_RSP_OK;
+ p_obx->p_pkt = NULL;
+ p_cb->req_pending = TRUE;
+ }
+ }
+
+ return (rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_cont_get_rsp
+**
+** Description Continues an obex get response packet.
+** This function is called upon completion of a file open or
+** a file write event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_cont_get_rsp(tBTA_OPC_CB *p_cb)
+{
+ tBTA_OPC_OBX_EVT obx_evt;
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 body_size;
+ BOOLEAN end;
+
+ /* Read the body header from the obx packet if it exists */
+ if (OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start, &body_size, &end))
+ {
+ p_obx->final_pkt = end;
+ if (body_size)
+ {
+ /* Data to be written */
+ p_obx->offset = body_size; /* Save write size for comparison */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, p_obx->p_start, body_size,
+ BTA_OPC_CI_WRITE_EVT, 0, p_cb->app_id);
+ return;
+ }
+ }
+
+ /* Empty Body; send next request or finished */
+ if (!p_obx->final_pkt)
+ {
+ bta_opc_send_get_req(p_cb);
+ }
+ else /* Done getting object */
+ {
+ memset(&obx_evt, 0, sizeof(tBTA_OPC_OBX_EVT));
+ obx_evt.rsp_code = OBX_RSP_OK;
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, (tBTA_OPC_DATA *) &obx_evt);
+ utl_freebuf((void**)&p_obx->p_pkt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_proc_get_rsp
+**
+** Description Processes an obex get response packet.
+** Initiates a file open if no errors.
+**
+**
+** Returns BOOLEAN - TRUE if obex packet is to be freed
+**
+*******************************************************************************/
+BOOLEAN bta_opc_proc_get_rsp(tBTA_OPC_CB *p_cb, tBTA_OPC_DATA *p_data)
+{
+ tBTA_OPC_OBX_EVT *p_evt = &p_data->obx_evt;
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ char *p_filename;
+
+ if (p_evt->rsp_code == OBX_RSP_OK || p_evt->rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* The get the file name */
+ if (!OBX_ReadUtf8NameHdr(p_obx->p_pkt, (UINT8 *) p_cb->p_name,
+ p_bta_fs_cfg->max_file_len))
+ BCM_STRNCPY_S(p_cb->p_name, p_bta_fs_cfg->max_path_len+1, OPC_DEF_RCV_NAME, sizeof(OPC_DEF_RCV_NAME)+1);
+
+ /* If length header exists, save the file length */
+ if (!OBX_ReadLengthHdr(p_obx->p_pkt, &p_cb->obj_size))
+ p_cb->obj_size = BTA_FS_LEN_UNKNOWN;
+
+ /* Build the file name with a fully qualified path */
+ if ((p_filename = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ sprintf(p_filename, "%s%c%s", p_cb->p_rcv_path,
+ p_bta_fs_cfg->path_separator,
+ p_cb->p_name);
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open(p_filename,
+ (BTA_FS_O_RDWR | BTA_FS_O_CREAT | BTA_FS_O_TRUNC),
+ p_cb->obj_size, BTA_OPC_CI_OPEN_EVT, p_cb->app_id);
+
+ GKI_freebuf(p_filename);
+ return FALSE; /* Do not free the obex packet until data is written */
+ }
+ else
+ p_evt->rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+
+ /* Server returned an error or out of memory to process request */
+ bta_opc_sm_execute(p_cb, BTA_OPC_OBX_CMPL_EVT, p_data);
+
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_send_put_req
+**
+** Description Initiates/Continues a Put Object Operation.
+** Builds a new OBX packet, and initiates a read operation.
+**
+** Parameters p_cb - pointer to the client's control block.
+** first_pkt - TRUE if initial PUT request to server.
+**
+**
+** Returns UINT8 OBX response code
+**
+*******************************************************************************/
+UINT8 bta_opc_send_put_req(tBTA_OPC_CB *p_cb, BOOLEAN first_pkt)
+{
+ tBTA_OPC_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_FAILED;
+ char *p_ch;
+
+ utl_freebuf((void**)&p_obx->p_pkt);
+ if ((p_obx->p_pkt = OBX_HdrInit(p_cb->obx_handle, OBX_LRG_DATA_POOL_SIZE)) != NULL)
+ {
+ /* Add length header if it exists; No body in first packet */
+ if (first_pkt)
+ {
+ /* Add the Name Header to the request */
+ /* Find the beginning of the name (excluding the path) */
+ p_ch = strrchr(p_cb->p_name, (int) p_bta_fs_cfg->path_separator);
+ if (p_ch == NULL)
+ p_ch = p_cb->p_name;
+
+ if (p_ch && p_ch[1] != '\0')
+ {
+ OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *) (&p_ch[1]));
+
+ /* Add the length header if known */
+ if (p_cb->obj_size != BTA_FS_LEN_UNKNOWN)
+ {
+ OBX_AddLengthHdr(p_obx->p_pkt, p_cb->obj_size);
+ }
+
+ /* Add the type header if known */
+ switch (p_cb->format)
+ {
+ case BTA_OP_VCARD30_FMT:
+ case BTA_OP_VCARD21_FMT:
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vcard");
+ break;
+ case BTA_OP_VCAL_FMT:
+ case BTA_OP_ICAL_FMT:
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vcalendar");
+ break;
+ case BTA_OP_VNOTE_FMT:
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vnote");
+ break;
+ case BTA_OP_VMSG_FMT:
+ OBX_AddTypeHdr(p_obx->p_pkt, "text/x-vmessage");
+ break;
+ }
+
+ OBX_PutReq(p_cb->obx_handle, FALSE, p_obx->p_pkt);
+ p_obx->p_pkt = NULL;
+ p_cb->req_pending = TRUE;
+ rsp_code = OBX_RSP_OK;
+ }
+ else
+ APPL_TRACE_ERROR1("Invalid file name [%s] feed, PutReq NOT sent.", p_cb->p_name);
+
+ }
+ else /* A continuation packet so read object data */
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ /* Read in the first packet's worth of data */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_read(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_OPC_CI_READ_EVT, 0, p_cb->app_id);
+ rsp_code = OBX_RSP_OK;
+ }
+ }
+
+ return (rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_start_push
+**
+** Description Push an object to connected server.
+** Opens the object to be transferred to the server.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_opc_start_push(tBTA_OPC_CB *p_cb)
+{
+ p_cb->to_do &= ~BTA_OPC_PUSH_MASK;
+ p_cb->obx_oper = OPC_OP_PUSH_OBJ;
+ p_cb->cout_active = TRUE;
+
+ bta_fs_co_open(p_cb->p_name, BTA_FS_O_RDONLY, 0, BTA_OPC_CI_OPEN_EVT,
+ p_cb->app_id);
+}
+
+/*******************************************************************************
+**
+** Function bta_opc_convert_obx_to_opc_status
+**
+** Description Convert OBX response code into BTA OPC status code.
+**
+** Returns void
+**
+*******************************************************************************/
+tBTA_OPC_STATUS bta_opc_convert_obx_to_opc_status(tOBX_STATUS obx_status)
+{
+ tBTA_OPC_STATUS status;
+
+ switch (obx_status)
+ {
+ case OBX_RSP_OK:
+ case OBX_RSP_CONTINUE:
+ status = BTA_OPC_OK;
+ break;
+ case OBX_RSP_UNAUTHORIZED:
+ status = BTA_OPC_NO_PERMISSION;
+ break;
+ case OBX_RSP_NOT_FOUND:
+ status = BTA_OPC_NOT_FOUND;
+ break;
+ case OBX_RSP_SERVICE_UNAVL:
+ status = BTA_OPC_SRV_UNAVAIL;
+ break;
+ case OBX_RSP_FORBIDDEN:
+ status = BTA_OPC_RSP_FORBIDDEN;
+ break;
+ case OBX_RSP_NOT_ACCEPTABLE:
+ status = BTA_OPC_RSP_NOT_ACCEPTABLE;
+ break;
+ default:
+ status = BTA_OPC_FAIL;
+ }
+
+ return (status);
+}
diff --git a/bta/op/bta_ops_act.c b/bta/op/bta_ops_act.c
new file mode 100644
index 0000000..5409cf1
--- /dev/null
+++ b/bta/op/bta_ops_act.c
@@ -0,0 +1,793 @@
+/*****************************************************************************
+**
+** Name: bta_ops_act.c
+**
+** Description: This file contains the object transfer action
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_OP_INCLUDED) && (BTA_OP_INCLUDED)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_op_api.h"
+#include "bta_ops_int.h"
+#include "bta_fs_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#include "rfcdefs.h" /* BT_PSM_RFCOMM */
+#include "btm_api.h"
+#include "utl.h"
+#include "goep_util.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+#define BTA_OPS_NUM_FMTS 7
+#define BTA_OPS_PROTOCOL_COUNT 3
+
+/* object format lookup table */
+const tBTA_OP_FMT bta_ops_obj_fmt[] =
+{
+ BTA_OP_VCARD21_FMT,
+ BTA_OP_VCARD30_FMT,
+ BTA_OP_VCAL_FMT,
+ BTA_OP_ICAL_FMT,
+ BTA_OP_VNOTE_FMT,
+ BTA_OP_VMSG_FMT,
+ BTA_OP_OTHER_FMT
+};
+
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if BTA_OPS_DEBUG == TRUE
+static char *ops_obx_evt_code(tOBX_EVENT evt_code);
+#endif
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ops_enable
+**
+** Description Perform necessary operations to enable object push.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_enable(tBTA_OPS_CB *p_cb, tBTA_OPS_API_ENABLE *p_data)
+{
+ tOBX_StartParams start_params;
+ UINT16 servclass = UUID_SERVCLASS_OBEX_OBJECT_PUSH;
+ int i, j;
+ tBTA_UTL_COD cod;
+ tOBX_STATUS status;
+ UINT8 desc_type[BTA_OPS_NUM_FMTS];
+ UINT8 type_len[BTA_OPS_NUM_FMTS];
+ UINT8 *type_value[BTA_OPS_NUM_FMTS];
+ UINT16 mtu = OBX_MAX_MTU;
+ UINT8 temp[4], *p;
+ UINT16 version = GOEP_ENHANCED_VERSION;
+
+ /* allocate scn for opp */
+ p_cb->scn = BTM_AllocateSCN();
+ p_cb->app_id = p_data->app_id;
+
+ /* set security level */
+ BTM_SetSecurityLevel (FALSE, (char *) "", BTM_SEC_SERVICE_OBEX,
+ p_data->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, p_cb->scn);
+
+ p_cb->psm = L2CA_AllocatePSM();
+ BTM_SetSecurityLevel (FALSE, (char *) "", BTM_SEC_SERVICE_OBEX,
+ p_data->sec_mask, p_cb->psm, 0, 0);
+
+ memset (&start_params, 0, sizeof(tOBX_StartParams));
+ start_params.p_target = NULL;
+ start_params.p_cback = &bta_ops_obx_cback;
+ start_params.mtu = mtu;
+ start_params.scn = p_cb->scn;
+ start_params.psm = p_cb->psm;
+ start_params.srm = p_cb->srm;
+ start_params.nonce = 0;
+ start_params.authenticate = FALSE;
+ start_params.auth_option = OBX_AO_NONE;
+ start_params.realm_charset = OBX_RCS_ASCII;
+ start_params.p_realm = NULL;
+ start_params.realm_len = 0;
+
+ if ((status = OBX_StartServer (&start_params, &p_cb->obx_handle)) == OBX_SUCCESS)
+ {
+ status = GOEP_Register (p_data->name, &p_cb->sdp_handle, p_cb->scn, 1, &servclass,
+ servclass, version);
+
+ /* add the psm */
+ p = temp;
+ UINT16_TO_BE_STREAM(p, p_cb->psm);
+ SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_OBX_OVR_L2CAP_PSM, UINT_DESC_TYPE,
+ (UINT32)2, (UINT8*)temp);
+
+ /* add sequence for supported types */
+ for (i = 0, j = 0; i < BTA_OPS_NUM_FMTS; i++)
+ {
+ if ((p_data->formats >> i) & 1)
+ {
+ type_value[j] = (UINT8 *) &bta_ops_obj_fmt[i];
+ desc_type[j] = UINT_DESC_TYPE;
+ type_len[j++] = 1;
+ }
+ }
+
+ SDP_AddSequence(p_cb->sdp_handle, (UINT16) ATTR_ID_SUPPORTED_FORMATS_LIST,
+ (UINT8) j, desc_type, type_len, type_value);
+
+ /* set class of device */
+ cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
+ utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+
+ /* store formats value */
+ p_cb->formats = p_data->formats;
+ }
+ bta_sys_add_uuid(servclass); /* UUID_SERVCLASS_OBEX_OBJECT_PUSH */
+
+ p_cb->p_cback(BTA_OPS_ENABLE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_api_disable
+**
+** Description Perform necessary operations to disable object push.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_api_disable(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ /* Free any outstanding headers and control block memory */
+ bta_ops_clean_getput(p_cb, TRUE);
+
+ /* Stop the OBEX server */
+ OBX_StopServer(p_cb->obx_handle);
+
+ /* Remove the OPP service from the SDP database */
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ bta_sys_remove_uuid(UUID_SERVCLASS_OBEX_OBJECT_PUSH);
+
+ /* Free the allocated server channel number */
+ BTM_FreeSCN(p_cb->scn);
+ BTM_SecClrService(BTM_SEC_SERVICE_OBEX);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_api_accessrsp
+**
+** Description Process the access API event.
+** If permission had been granted, continue the push or pull
+** operation.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_api_accessrsp(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ UINT8 rsp_code;
+
+ /* Process the currently active access response */
+ switch (p_cb->acc_active)
+ {
+ case BTA_OP_OPER_PUSH:
+ if (p_data->api_access.oper == BTA_OP_OPER_PUSH)
+ {
+ if (p_data->api_access.flag == BTA_OP_ACCESS_ALLOW)
+ {
+ /* Save the file name with path prepended */
+ BCM_STRCPY_S(p_cb->p_path, p_bta_fs_cfg->max_path_len+1, p_data->api_access.p_name);
+
+ APPL_TRACE_DEBUG2("OPS PUSH OBJ: Name [%s], Length = 0x%0x (0 = n/a)",
+ p_cb->p_path, p_cb->file_length);
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open (p_cb->p_path,
+ (BTA_FS_O_CREAT | BTA_FS_O_TRUNC | BTA_FS_O_RDWR),
+ p_cb->file_length, BTA_OPS_CI_OPEN_EVT,
+ p_cb->app_id);
+ }
+ else /* Access denied or Unsupported */
+ {
+ rsp_code = (p_data->api_access.flag == BTA_OP_ACCESS_NONSUP)
+ ? OBX_RSP_UNSUPTD_TYPE : OBX_RSP_UNAUTHORIZED;
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+ p_cb->acc_active = 0;
+ }
+
+ break;
+
+ case BTA_OP_OPER_PULL:
+ if (p_data->api_access.oper == BTA_OP_OPER_PULL)
+ {
+ if (p_data->api_access.flag == BTA_OP_ACCESS_ALLOW)
+ {
+ /* Save the file name with path prepended */
+ BCM_STRCPY_S(p_cb->p_path, p_bta_fs_cfg->max_path_len+1, p_data->api_access.p_name);
+
+ APPL_TRACE_DEBUG1("OPS PULL VCARD: Name [%s]", p_cb->p_path);
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_open (p_cb->p_path, BTA_FS_O_RDONLY, 0,
+ BTA_OPS_CI_OPEN_EVT, p_cb->app_id);
+ }
+ else /* Denied */
+ bta_ops_get_obj_rsp(OBX_RSP_UNAUTHORIZED, 0);
+
+ p_cb->acc_active = 0;
+ }
+ break;
+
+ default:
+ APPL_TRACE_WARNING1("OPS ACCRSP: Unknown tBTA_OP_OPER value (%d)",
+ p_cb->acc_active);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_api_close
+**
+** Description Handle an api close event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_api_close(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ /* resources will be freed at BTA_OPS_OBX_CLOSE_EVT */
+ OBX_DisconnectRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_ci_write
+**
+** Description Continue with the current write operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_ci_write(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ p_cb->cout_active = FALSE;
+
+ if (!p_cb->aborting)
+ {
+ /* Process write call-in event if operation is still active */
+ if (p_cb->obx_oper == OPS_OP_PUSH_OBJ)
+ {
+ if (p_data->write_evt.status == BTA_FS_CO_OK)
+ rsp_code = OBX_RSP_OK;
+ else
+ {
+ if (p_data->write_evt.status == BTA_FS_CO_ENOSPACE)
+ rsp_code = OBX_RSP_DATABASE_FULL;
+ bta_ops_clean_getput(p_cb, TRUE);
+ }
+
+ /* Process response to OBX client */
+ bta_ops_put_obj_rsp(rsp_code);
+ }
+ }
+ else /* Finish aborting */
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_ci_read
+**
+** Description Handles the response to a read call-out request.
+** This is called within the OBX get file request. If the
+** operation has completed, the OBX response is sent out;
+** otherwise a read for additional data is made.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_ci_read(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_FS_CI_READ_EVT *p_revt = &p_data->read_evt;
+ UINT8 rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ p_cb->cout_active = FALSE;
+
+ if (!p_cb->aborting)
+ {
+ /* Process read call-in event if operation is still active */
+ if (p_cb->obx_oper == OPS_OP_PULL_OBJ && p_revt->fd == p_cb->fd)
+ {
+ /* Read was successful, not finished yet */
+ if (p_revt->status == BTA_FS_CO_OK)
+ rsp_code = OBX_RSP_CONTINUE;
+
+ /* Read was successful, end of file has been detected */
+ else if (p_revt->status == BTA_FS_CO_EOF)
+ rsp_code = OBX_RSP_OK;
+
+ /* Process response to OBX client */
+ bta_ops_get_obj_rsp(rsp_code, p_revt->num_read);
+ }
+ }
+ else /* Finish aborting */
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ APPL_TRACE_ERROR0("OPS PUSH OBJ: Finished ABORTING!!!");
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_ci_open
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_ci_open(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_FS_CI_OPEN_EVT *p_open = &p_data->open_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+ UINT8 num_hdrs;
+ BOOLEAN endpkt;
+ char *p_name;
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ return;
+ }
+
+ /* Only process file get or put operations */
+ if (p_cb->obx_oper == OPS_OP_PULL_OBJ)
+ {
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->fd = p_open->fd;
+ p_cb->file_length = p_open->file_size;
+
+ /* Add the name and length headers */
+ p_name = strrchr(p_cb->p_path, (int)p_bta_fs_cfg->path_separator);
+ if (p_name == NULL)
+ p_name = p_cb->p_path;
+ else
+ p_name++; /* increment past the file separator */
+
+ OBX_AddUtf8NameHdr(p_obx->p_pkt, (UINT8 *)p_name);
+
+ if (p_cb->file_length != BTA_FS_LEN_UNKNOWN)
+ {
+ OBX_AddLengthHdr(p_obx->p_pkt, p_cb->file_length);
+ if (p_cb->file_length > 0)
+ {
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ }
+
+ /* Send continuation response with the length of the file and no body */
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+ }
+ else
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else /* File could not be found */
+ rsp_code = OBX_RSP_NOT_FOUND;
+
+ /* Send OBX response if an error occurred */
+ bta_ops_get_obj_rsp(rsp_code, 0);
+ }
+ }
+ else if (p_cb->obx_oper == OPS_OP_PUSH_OBJ)
+ {
+ /* if file is accessible read/write the first buffer of data */
+ if (p_open->status == BTA_FS_CO_OK)
+ {
+ p_cb->fd = p_open->fd;
+
+ /* Read in start of body if there is a body header */
+ num_hdrs = OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start,
+ &p_obx->bytes_left, &endpkt);
+ if (num_hdrs == 1)
+ {
+ rsp_code = OBX_RSP_PART_CONTENT; /* Do not send OBX response yet */
+
+ /* Initiate the writing out of the data */
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_OPS_CI_WRITE_EVT,
+ 0, p_cb->app_id);
+ }
+ else if (num_hdrs > 1) /* Too many body headers to handle */
+ {
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ bta_ops_clean_getput(p_cb, TRUE);
+ }
+ else /* No body: respond with an OK so client can start sending the data */
+ p_obx->bytes_left = 0;
+ }
+ else
+ {
+ if (p_open->status == BTA_FS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else if (p_open->status == BTA_FS_CO_ENOSPACE)
+ rsp_code = OBX_RSP_DATABASE_FULL;
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+
+ /* Send OBX response now if an error occurred or no body */
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_ops_put_obj_rsp(rsp_code);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_connect
+**
+** Description Process the OBX connect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_connect(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+
+ p_cb->peer_mtu = p_evt->param.conn.mtu;
+ memcpy(p_cb->bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN);
+ APPL_TRACE_EVENT1("OPS Connect: peer mtu 0x%04x", p_cb->peer_mtu);
+
+ /* done with obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ OBX_ConnectRsp(p_evt->handle, OBX_RSP_OK, (BT_HDR *)NULL);
+
+ /* inform role manager */
+ bta_sys_conn_open( BTA_ID_OPS ,p_cb->app_id, bta_ops_cb.bd_addr);
+
+ /* Notify the MMI that a connection has been opened */
+ p_cb->p_cback(BTA_OPS_OPEN_EVT, (tBTA_OPS*)bta_ops_cb.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_disc
+**
+** Description Process the OBX disconnect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_disc(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code;
+
+ rsp_code = (p_evt->obx_event == OBX_DISCONNECT_REQ_EVT) ? OBX_RSP_OK
+ : OBX_RSP_BAD_REQUEST;
+
+ /* Action operation is not supported in OPP, send reject rsp and free data */
+ if(p_evt->obx_event == OBX_ACTION_REQ_EVT)
+ {
+ OBX_ActionRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ }
+
+ OBX_DisconnectRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_close
+**
+** Description Process the OBX link lost event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_close(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->cout_active)
+ bta_ops_sm_execute(p_cb, BTA_OPS_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_abort
+**
+** Description Process the OBX abort event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_abort(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (!p_cb->cout_active)
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+ else /* Delay the response if a call-out function is active */
+ p_cb->aborting = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_put
+**
+** Description Process the OBX push object put event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_put(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_CONTINUE;
+
+ p_cb->obx.final_pkt = p_evt->param.put.final;
+
+ /* If currently processing a push, use the current name */
+ if (bta_ops_cb.obx_oper == OPS_OP_PUSH_OBJ)
+ {
+ bta_ops_proc_put_obj(p_evt->p_pkt);
+ }
+
+ /* This is a new request; allocate enough memory to hold the path (including file name) */
+ else if ((p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len
+ + p_bta_fs_cfg->max_file_len + 2))) != NULL)
+ {
+ p_cb->p_name = (p_cb->p_path + p_bta_fs_cfg->max_path_len + 1);
+ p_cb->p_name[p_bta_fs_cfg->max_file_len] = '\0';
+ p_cb->p_path[p_bta_fs_cfg->max_path_len] = '\0';
+
+ /* read the name header if it exists */
+ if (OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+ /* get file type from file name; check if supported */
+ if ((p_cb->obj_fmt = bta_ops_fmt_supported(p_cb->p_name,
+ p_cb->formats)) != 0)
+ {
+ if(!(OBX_ReadLengthHdr(p_evt->p_pkt, &p_cb->file_length)))
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+
+ p_cb->obx.p_pkt = p_evt->p_pkt; /* save the packet for later use */
+ p_cb->obx.offset = 0; /* Initial offset into OBX data */
+ p_cb->obx_oper = OPS_OP_PUSH_OBJ;
+
+ /* request access from the app */
+ bta_ops_req_app_access (BTA_OP_OPER_PUSH, p_cb);
+ }
+ else
+ rsp_code = OBX_RSP_UNSUPTD_TYPE;
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+
+ /* Error has been detected; respond with error code */
+ if (rsp_code != OBX_RSP_CONTINUE)
+ {
+ utl_freebuf((void**)&p_evt->p_pkt); /* done with obex packet */
+ utl_freebuf((void**)&p_cb->p_path);
+ p_cb->p_name = NULL;
+ OBX_PutRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_obx_get
+**
+** Description Process the OBX pull vCard object.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_get(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ /* this is a new request; validate it */
+ if (bta_ops_cb.obx_oper != OPS_OP_PULL_OBJ)
+ bta_ops_init_get_obj(p_cb, p_data);
+ else /* this is a continuation request */
+ bta_ops_proc_get_obj(p_cb);
+
+ /* done with Obex packet */
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_close_complete
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_close_complete(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_OPS ,p_cb->app_id, bta_ops_cb.bd_addr);
+
+ p_cb->cout_active = FALSE;
+
+ bta_ops_clean_getput(p_cb, TRUE);
+
+ /* Notify the MMI that a connection has been closed */
+ p_cb->p_cback(BTA_OPS_CLOSE_EVT, (tBTA_OPS*)p_cb->bd_addr);
+ memset(p_cb->bd_addr, 0, BD_ADDR_LEN);
+
+ if (p_data->obx_evt.p_pkt)
+ APPL_TRACE_WARNING0("OPS: OBX CLOSE CALLED WITH non-NULL Packet!!!");
+}
+
+/*****************************************************************************
+** Callback Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ops_obx_cback
+**
+** Description OBX callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_OPS_OBX_EVENT *p_obx_msg;
+ UINT16 event = 0;
+
+#if BTA_OPS_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("OBX Event Callback: ops_obx_event[%s]", ops_obx_evt_code(obx_event));
+#endif
+
+ switch(obx_event)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ event = BTA_OPS_OBX_CONN_EVT;
+ break;
+ case OBX_DISCONNECT_REQ_EVT:
+ event = BTA_OPS_OBX_DISC_EVT;
+ break;
+ case OBX_PUT_REQ_EVT:
+ event = BTA_OPS_OBX_PUT_EVT;
+ break;
+ case OBX_GET_REQ_EVT:
+ event = BTA_OPS_OBX_GET_EVT;
+ break;
+ case OBX_ABORT_REQ_EVT:
+ event = BTA_OPS_OBX_ABORT_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_OPS_OBX_CLOSE_EVT;
+ break;
+ case OBX_TIMEOUT_EVT:
+ break;
+ default:
+ /* Unrecognized packet; disconnect the session */
+ if (p_pkt)
+ event = BTA_OPS_OBX_DISC_EVT;
+ }
+
+ /* send event to BTA, if any */
+ if (event && (p_obx_msg =
+ (tBTA_OPS_OBX_EVENT *) GKI_getbuf(sizeof(tBTA_OPS_OBX_EVENT))) != NULL)
+ {
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_OPS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function ops_obx_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ops_obx_evt_code(tOBX_EVENT evt_code)
+{
+ switch(evt_code)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ return "OBX_CONNECT_REQ_EVT";
+ case OBX_DISCONNECT_REQ_EVT:
+ return "OBX_DISCONNECT_REQ_EVT";
+ case OBX_PUT_REQ_EVT:
+ return "OBX_PUT_REQ_EVT";
+ case OBX_GET_REQ_EVT:
+ return "OBX_GET_REQ_EVT";
+ case OBX_SETPATH_REQ_EVT:
+ return "OBX_SETPATH_REQ_EVT";
+ case OBX_ABORT_REQ_EVT:
+ return "OBX_ABORT_REQ_EVT";
+ case OBX_CLOSE_IND_EVT:
+ return "OBX_CLOSE_IND_EVT";
+ case OBX_TIMEOUT_EVT:
+ return "OBX_TIMEOUT_EVT";
+ case OBX_PASSWORD_EVT:
+ return "OBX_PASSWORD_EVT";
+ case OBX_SESSION_REQ_EVT:
+ return "OBX_SESSION_REQ_EVT";
+ case OBX_ACTION_REQ_EVT:
+ return "OBX_ACTION_REQ_EVT";
+ default:
+ return "unknown OBX event code";
+ }
+}
+#endif /* Debug Functions */
+#endif /* BTA_OP_INCLUDED */
diff --git a/bta/op/bta_ops_api.c b/bta/op/bta_ops_api.c
new file mode 100644
index 0000000..1c09094
--- /dev/null
+++ b/bta/op/bta_ops_api.c
@@ -0,0 +1,153 @@
+/*****************************************************************************
+**
+** Name: bta_ops_api.c
+**
+** Description: This is the implementation of the API for the object
+** push server subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_OP_INCLUDED) && (BTA_OP_INCLUDED)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_fs_api.h"
+#include "bta_op_api.h"
+#include "bta_ops_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_ops_reg =
+{
+ bta_ops_hdl_event,
+ BTA_OpsDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_OpsEnable
+**
+** Description Enable the object push server. This function must be
+** called before any other functions in the OPS API are called.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpsEnable(tBTA_SEC sec_mask, tBTA_OP_FMT_MASK formats,
+ char *p_service_name, tBTA_OPS_CBACK *p_cback, BOOLEAN srm, UINT8 app_id)
+{
+ tBTA_OPS_API_ENABLE *p_buf;
+
+ GKI_sched_lock();
+ /* register with BTA system manager */
+ bta_sys_register(BTA_ID_OPS, &bta_ops_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_OPS_API_ENABLE *) GKI_getbuf(sizeof(tBTA_OPS_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_OPS_API_ENABLE_EVT;
+ BCM_STRNCPY_S(p_buf->name, sizeof(p_buf->name), p_service_name, BTA_SERVICE_NAME_LEN);
+ p_buf->name[BTA_SERVICE_NAME_LEN] = '\0';
+ p_buf->p_cback = p_cback;
+ p_buf->app_id = app_id;
+ p_buf->formats = formats;
+ p_buf->sec_mask = sec_mask;
+ p_buf->srm = srm;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpsDisable
+**
+** Description Disable the object push server. If the server is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpsDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_OPS);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_OPS_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpsClose
+**
+** Description Close the current connection. This function is called if
+** the phone wishes to close the connection before the object
+** push is completed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpsClose(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_OPS_API_CLOSE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_OpsAccessRsp
+**
+** Description Sends a reply to an access request event (BTA_OPS_ACCESS_EVT).
+** This call MUST be made whenever the event occurs.
+**
+** Parameters oper - operation being accessed.
+** access - BTA_OP_ACCESS_ALLOW, BTA_OP_ACCESS_FORBID, or
+** BTA_OP_ACCESS_NONSUP.
+** p_name - Full path of file to read from (pull) or write to
+** (push).
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_OpsAccessRsp(tBTA_OP_OPER oper, tBTA_OP_ACCESS access, char *p_name)
+{
+ tBTA_OPS_API_ACCESSRSP *p_buf;
+
+ if ((p_buf = (tBTA_OPS_API_ACCESSRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_OPS_API_ACCESSRSP)
+ + p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ p_buf->flag = access;
+ p_buf->oper = oper;
+ p_buf->p_name = (char *)(p_buf + 1);
+ if (p_name)
+ {
+ BCM_STRNCPY_S(p_buf->p_name, p_bta_fs_cfg->max_path_len+1, p_name, p_bta_fs_cfg->max_path_len);
+ p_buf->p_name[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+ else
+ *p_buf->p_name = '\0';
+
+ p_buf->hdr.event = BTA_OPS_API_ACCESSRSP_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+#endif /* BTA_OP_INCLUDED */
diff --git a/bta/op/bta_ops_int.h b/bta/op/bta_ops_int.h
new file mode 100644
index 0000000..733b9ae
--- /dev/null
+++ b/bta/op/bta_ops_int.h
@@ -0,0 +1,198 @@
+/*****************************************************************************
+**
+** Name: bta_ops_int.h
+**
+** Description: This is the private file for the object transfer
+** server (OPS).
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_OPS_INT_H
+#define BTA_OPS_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_op_api.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+
+/*****************************************************************************
+** Constants and data types
+*****************************************************************************/
+
+
+/* OPS active obex operation (Valid in connected state) */
+#define OPS_OP_NONE 0
+#define OPS_OP_PULL_OBJ 1
+#define OPS_OP_PUSH_OBJ 2
+
+/* state machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_OPS_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_OPS),
+
+ BTA_OPS_API_ACCESSRSP_EVT, /* Response to an access request */
+ BTA_OPS_API_CLOSE_EVT, /* Close API */
+ BTA_OPS_CI_OPEN_EVT, /* Response to File Open request */
+ BTA_OPS_CI_WRITE_EVT, /* Response to Write request */
+ BTA_OPS_CI_READ_EVT, /* Response to Read request */
+ BTA_OPS_OBX_CONN_EVT, /* OBX Channel Connect Request */
+ BTA_OPS_OBX_DISC_EVT, /* OBX Channel Disconnect */
+ BTA_OPS_OBX_ABORT_EVT, /* OBX_operation aborted */
+ BTA_OPS_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_OPS_OBX_PUT_EVT, /* Write file data or delete */
+ BTA_OPS_OBX_GET_EVT, /* Read file data or folder listing */
+ BTA_OPS_CLOSE_CMPL_EVT, /* Finished closing channel */
+
+ /* these events are handled outside the state machine */
+ BTA_OPS_API_ENABLE_EVT
+};
+
+typedef UINT16 tBTA_OPS_INT_EVT;
+
+typedef UINT8 tBTA_OPS_STATE;
+
+/* data type for BTA_OPS_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char name[BTA_SERVICE_NAME_LEN + 1];
+ tBTA_OPS_CBACK *p_cback;
+ tBTA_OP_FMT_MASK formats;
+ UINT8 sec_mask;
+ BOOLEAN srm;
+ UINT8 app_id;
+} tBTA_OPS_API_ENABLE;
+
+/* data type for BTA_OPS_API_ACCESSRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_name;
+ tBTA_OP_OPER oper;
+ tBTA_OP_ACCESS flag;
+} tBTA_OPS_API_ACCESSRSP;
+
+/* data type for all obex events
+ hdr.event contains the OPS event
+*/
+typedef struct
+{
+ BT_HDR hdr;
+ tOBX_HANDLE handle;
+ tOBX_EVT_PARAM param;
+ BT_HDR *p_pkt;
+ tOBX_EVENT obx_event;
+ UINT8 rsp_code;
+} tBTA_OPS_OBX_EVENT;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_OPS_API_ENABLE api_enable;
+ tBTA_OPS_API_ACCESSRSP api_access;
+ tBTA_OPS_OBX_EVENT obx_evt;
+ tBTA_FS_CI_OPEN_EVT open_evt;
+ tBTA_FS_CI_READ_EVT read_evt;
+ tBTA_FS_CI_WRITE_EVT write_evt;
+} tBTA_OPS_DATA;
+
+/* OBX Response Packet Structure - Holds current response packet info */
+typedef struct
+{
+ BT_HDR *p_pkt; /* (Pull/Push) Holds the current OBX hdr for Push or Pull */
+ UINT8 *p_start; /* (Pull/Push) Start of the Body of the packet */
+ UINT16 offset; /* (Pull/Push) Contains the current offset into the Body (p_start) */
+ UINT16 bytes_left; /* (Pull/Push) Holds bytes available left in Obx packet */
+ BOOLEAN final_pkt; /* (Push) Holds the final bit of the Push packet */
+} tBTA_OPS_OBX_PKT;
+
+/* Power management state for OPS */
+#define BTA_OPS_PM_BUSY 0
+#define BTA_OPS_PM_IDLE 1
+
+/* OPS control block */
+typedef struct
+{
+ tBTA_OPS_CBACK *p_cback; /* pointer to application callback function */
+ char *p_name; /* Holds name of current operation */
+ char *p_path; /* Holds path of current operation */
+ tBTA_OPS_OBX_PKT obx; /* Holds the current OBX packet information */
+ UINT32 sdp_handle; /* SDP record handle */
+ UINT32 file_length; /* length of file being Push/Pull */
+ int fd; /* File Descriptor of opened file */
+ BD_ADDR bd_addr; /* Device currently connected to */
+ tOBX_HANDLE obx_handle;
+ UINT16 peer_mtu;
+ UINT16 psm; /* PSM for Obex Over L2CAP */
+ BOOLEAN srm; /* TRUE, to use SIngle Response Mode */
+ UINT8 scn; /* SCN of the OPP server */
+ tBTA_OP_FMT_MASK formats; /* supported object formats */
+ tBTA_OPS_STATE state; /* state machine state */
+ tBTA_OP_FMT obj_fmt; /* file format of received object */
+ UINT8 obx_oper; /* current active OBX operation PUSH OBJ, or PULL OBJ */
+ UINT8 app_id;
+ tBTA_OP_OPER acc_active; /* op code when waiting for an access rsp (API) (0 not active) */
+ BOOLEAN cout_active; /* TRUE when waiting for a call-in function */
+ BOOLEAN aborting; /* TRUE when waiting for a call-in function */
+ UINT8 pm_state;
+} tBTA_OPS_CB;
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* OPS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_OPS_CB bta_ops_cb;
+#else
+extern tBTA_OPS_CB *bta_ops_cb_ptr;
+#define bta_ops_cb (*bta_ops_cb_ptr)
+#endif
+
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern BOOLEAN bta_ops_hdl_event(BT_HDR *p_msg);
+extern void bta_ops_sm_execute(tBTA_OPS_CB *p_cb, UINT16 event, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt);
+
+/* action functions */
+extern void bta_ops_api_disable(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_api_accessrsp(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_api_close(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_ci_write(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_ci_read(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_ci_open(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_connect(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_disc(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_close(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_abort(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_put(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_obx_get(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_gasp_err_rsp(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_close_complete(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+
+/* object store */
+extern void bta_ops_init_get_obj(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+extern void bta_ops_proc_get_obj(tBTA_OPS_CB *p_cb);
+extern void bta_ops_proc_put_obj(BT_HDR *p_pkt);
+
+/* miscellaneous functions */
+extern void bta_ops_enable(tBTA_OPS_CB *p_cb, tBTA_OPS_API_ENABLE *p_data);
+extern void bta_ops_get_obj_rsp(UINT8 rsp_code, UINT16 num_read);
+extern void bta_ops_put_obj_rsp(UINT8 rsp_code);
+extern void bta_ops_clean_getput(tBTA_OPS_CB *p_cb, BOOLEAN is_aborted);
+extern void bta_ops_discard_data(UINT16 event, tBTA_OPS_DATA *p_data);
+extern void bta_ops_req_app_access (tBTA_OP_OPER oper, tBTA_OPS_CB *p_cb);
+extern tBTA_OP_FMT bta_ops_fmt_supported(char *p, tBTA_OP_FMT_MASK fmt_mask);
+
+#endif /* BTA_OPS_INT_H */
diff --git a/bta/op/bta_ops_main.c b/bta/op/bta_ops_main.c
new file mode 100644
index 0000000..f98b43b
--- /dev/null
+++ b/bta/op/bta_ops_main.c
@@ -0,0 +1,412 @@
+/*****************************************************************************
+**
+** Name: bta_ops_main.c
+**
+** Description: This file contains the file transfer server main functions
+** and state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_OP_INCLUDED) && (BTA_OP_INCLUDED)
+
+#include <string.h>
+
+#include "bta_fs_api.h"
+#include "bta_ops_int.h"
+#include "gki.h"
+#include "obx_api.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+ BTA_OPS_IDLE_ST = 0, /* Idle */
+ BTA_OPS_LISTEN_ST, /* Listen - waiting for OBX/RFC connection */
+ BTA_OPS_CONN_ST, /* Connected - OPP Session is active */
+ BTA_OPS_CLOSING_ST /* Closing is in progress */
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_OPS_API_DISABLE,
+ BTA_OPS_API_ACCESSRSP,
+ BTA_OPS_API_CLOSE,
+ BTA_OPS_CI_WRITE,
+ BTA_OPS_CI_READ,
+ BTA_OPS_CI_OPEN,
+ BTA_OPS_OBX_CONNECT,
+ BTA_OPS_OBX_DISC,
+ BTA_OPS_OBX_CLOSE,
+ BTA_OPS_OBX_ABORT,
+ BTA_OPS_OBX_PUT,
+ BTA_OPS_OBX_GET,
+ BTA_OPS_CLOSE_COMPLETE,
+ BTA_OPS_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_OPS_ACTION)(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data);
+
+/* action function list */
+const tBTA_OPS_ACTION bta_ops_action[] =
+{
+ bta_ops_api_disable,
+ bta_ops_api_accessrsp,
+ bta_ops_api_close,
+ bta_ops_ci_write,
+ bta_ops_ci_read,
+ bta_ops_ci_open,
+ bta_ops_obx_connect,
+ bta_ops_obx_disc,
+ bta_ops_obx_close,
+ bta_ops_obx_abort,
+ bta_ops_obx_put,
+ bta_ops_obx_get,
+ bta_ops_close_complete
+};
+
+
+/* state table information */
+#define BTA_OPS_ACTIONS 1 /* number of actions */
+#define BTA_OPS_NEXT_STATE 1 /* position of next state */
+#define BTA_OPS_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_ops_st_idle[][BTA_OPS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_OPS_API_DISABLE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_ACCESSRSP_EVT */ {BTA_OPS_IGNORE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_CLOSE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_IDLE_ST},
+};
+
+/* state table for obex/rfcomm connection state */
+static const UINT8 bta_ops_st_listen[][BTA_OPS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_OPS_API_DISABLE_EVT */ {BTA_OPS_API_DISABLE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_ACCESSRSP_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_API_CLOSE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_OPEN_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_WRITE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_READ_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_CONN_EVT */ {BTA_OPS_OBX_CONNECT, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_DISC_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_ABORT_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_CLOSE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_PUT_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_GET_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CLOSE_CMPL_EVT */ {BTA_OPS_IGNORE, BTA_OPS_LISTEN_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_ops_st_connected[][BTA_OPS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_OPS_API_DISABLE_EVT */ {BTA_OPS_API_DISABLE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_ACCESSRSP_EVT */ {BTA_OPS_API_ACCESSRSP, BTA_OPS_CONN_ST},
+/* BTA_OPS_API_CLOSE_EVT */ {BTA_OPS_API_CLOSE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_CI_OPEN_EVT */ {BTA_OPS_CI_OPEN, BTA_OPS_CONN_ST},
+/* BTA_OPS_CI_WRITE_EVT */ {BTA_OPS_CI_WRITE, BTA_OPS_CONN_ST},
+/* BTA_OPS_CI_READ_EVT */ {BTA_OPS_CI_READ, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_CONN_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_DISC_EVT */ {BTA_OPS_OBX_DISC, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_ABORT_EVT */ {BTA_OPS_OBX_ABORT, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_CLOSE_EVT */ {BTA_OPS_OBX_CLOSE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_PUT_EVT */ {BTA_OPS_OBX_PUT, BTA_OPS_CONN_ST},
+/* BTA_OPS_OBX_GET_EVT */ {BTA_OPS_OBX_GET, BTA_OPS_CONN_ST},
+/* BTA_OPS_CLOSE_CMPL_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CONN_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_ops_st_closing[][BTA_OPS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_OPS_API_DISABLE_EVT */ {BTA_OPS_API_DISABLE, BTA_OPS_IDLE_ST},
+/* BTA_OPS_API_ACCESSRSP_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_API_CLOSE_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_CI_OPEN_EVT */ {BTA_OPS_CLOSE_COMPLETE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_WRITE_EVT */ {BTA_OPS_CLOSE_COMPLETE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_CI_READ_EVT */ {BTA_OPS_CLOSE_COMPLETE, BTA_OPS_LISTEN_ST},
+/* BTA_OPS_OBX_CONN_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_DISC_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_ABORT_EVT */ {BTA_OPS_OBX_ABORT, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_CLOSE_EVT */ {BTA_OPS_OBX_CLOSE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_PUT_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_OBX_GET_EVT */ {BTA_OPS_IGNORE, BTA_OPS_CLOSING_ST},
+/* BTA_OPS_CLOSE_CMPL_EVT */ {BTA_OPS_CLOSE_COMPLETE, BTA_OPS_LISTEN_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_OPS_ST_TBL)[BTA_OPS_NUM_COLS];
+
+/* state table */
+const tBTA_OPS_ST_TBL bta_ops_st_tbl[] =
+{
+ bta_ops_st_idle,
+ bta_ops_st_listen,
+ bta_ops_st_connected,
+ bta_ops_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* OPS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_OPS_CB bta_ops_cb;
+#endif
+
+#if BTA_OPS_DEBUG == TRUE
+static char *ops_evt_code(tBTA_OPS_INT_EVT evt_code);
+static char *ops_state_code(tBTA_OPS_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_ops_sm_execute
+**
+** Description State machine event handling function for OPS
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_sm_execute(tBTA_OPS_CB *p_cb, UINT16 event, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_ST_TBL state_table;
+ UINT8 action;
+ int i;
+#if BTA_OPS_DEBUG == TRUE
+ tBTA_OPS_STATE in_state = bta_ops_cb.state;
+ UINT16 in_event = event;
+ APPL_TRACE_EVENT3("OPS Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ ops_state_code(in_state),
+ ops_evt_code(event));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_ops_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_OPS_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_OPS_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_OPS_IGNORE)
+ {
+ (*bta_ops_action[action])(p_cb, p_data);
+ }
+ else
+ {
+ /* discard ops data */
+ bta_ops_discard_data(p_data->hdr.event, p_data);
+ break;
+ }
+ }
+
+#if BTA_OPS_DEBUG == TRUE
+ if (in_state != bta_ops_cb.state)
+ {
+ APPL_TRACE_DEBUG3("OPS State Change: [%s] -> [%s] after Event [%s]",
+ ops_state_code(in_state),
+ ops_state_code(bta_ops_cb.state),
+ ops_evt_code(in_event));
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_api_enable
+**
+** Description Handle an api enable event. This function enables the OP
+** Server by opening an Obex/Rfcomm channel and placing it into
+** listen mode.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_ops_api_enable(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_API_ENABLE *p_enable = &p_data->api_enable;
+
+ /* initialize control block */
+ memset(p_cb, 0, sizeof(tBTA_OPS_CB));
+ p_cb->p_cback = p_enable->p_cback;
+ p_cb->app_id = p_enable->app_id;
+ p_cb->srm = p_enable->srm;
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ bta_ops_cb.state = BTA_OPS_LISTEN_ST;
+
+ /* call enable action function */
+ bta_ops_enable(p_cb, p_enable);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_hdl_event
+**
+** Description File transfer server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_ops_hdl_event(BT_HDR *p_msg)
+{
+#if BTA_OPS_DEBUG == TRUE
+ tBTA_OPS_STATE in_state = bta_ops_cb.state;
+#endif
+
+ switch (p_msg->event)
+ {
+ case BTA_OPS_API_ENABLE_EVT:
+#if BTA_OPS_DEBUG == TRUE
+ APPL_TRACE_EVENT3("OPS Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ ops_state_code(in_state),
+ ops_evt_code(p_msg->event));
+#endif
+ bta_ops_api_enable(&bta_ops_cb, (tBTA_OPS_DATA *) p_msg);
+
+#if BTA_OPS_DEBUG == TRUE
+ if (in_state != bta_ops_cb.state)
+ {
+ APPL_TRACE_DEBUG3("OPS State Change: [%s] -> [%s] after Event [%s]",
+ ops_state_code(in_state),
+ ops_state_code(bta_ops_cb.state),
+ ops_evt_code(p_msg->event));
+ }
+#endif
+ break;
+
+ default:
+
+ bta_ops_sm_execute(&bta_ops_cb, p_msg->event, (tBTA_OPS_DATA *) p_msg);
+
+ if ( bta_ops_cb.state == BTA_OPS_CONN_ST )
+ {
+ if (( bta_ops_cb.pm_state == BTA_OPS_PM_IDLE )
+ &&( bta_ops_cb.obx_oper != OPS_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA OPS informs DM/PM busy state");
+ bta_sys_busy( BTA_ID_OPS ,bta_ops_cb.app_id, bta_ops_cb.bd_addr);
+ bta_ops_cb.pm_state = BTA_OPS_PM_BUSY;
+ }
+ else if (( bta_ops_cb.pm_state == BTA_OPS_PM_BUSY )
+ &&( bta_ops_cb.obx_oper == OPS_OP_NONE ))
+ {
+ /* inform power manager */
+ APPL_TRACE_DEBUG0("BTA OPS informs DM/PM idle state");
+ bta_sys_idle( BTA_ID_OPS ,bta_ops_cb.app_id, bta_ops_cb.bd_addr);
+ bta_ops_cb.pm_state = BTA_OPS_PM_IDLE;
+ }
+ }
+ else if ( bta_ops_cb.state == BTA_OPS_LISTEN_ST )
+ {
+ /* initialize power management state */
+ bta_ops_cb.pm_state = BTA_OPS_PM_BUSY;
+ }
+
+ break;
+ }
+
+ return (TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_OPS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function ops_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ops_evt_code(tBTA_OPS_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_OPS_API_DISABLE_EVT:
+ return "BTA_OPS_API_DISABLE_EVT";
+ case BTA_OPS_API_ACCESSRSP_EVT:
+ return "BTA_OPS_API_ACCESSRSP_EVT";
+ case BTA_OPS_API_CLOSE_EVT:
+ return "BTA_OPS_API_CLOSE_EVT";
+ case BTA_OPS_CI_OPEN_EVT:
+ return "BTA_OPS_CI_OPEN_EVT";
+ case BTA_OPS_CI_WRITE_EVT:
+ return "BTA_OPS_CI_WRITE_EVT";
+ case BTA_OPS_CI_READ_EVT:
+ return "BTA_OPS_CI_READ_EVT";
+ case BTA_OPS_OBX_CONN_EVT:
+ return "BTA_OPS_OBX_CONN_EVT";
+ case BTA_OPS_OBX_DISC_EVT:
+ return "BTA_OPS_OBX_DISC_EVT";
+ case BTA_OPS_OBX_ABORT_EVT:
+ return "BTA_OPS_OBX_ABORT_EVT";
+ case BTA_OPS_OBX_CLOSE_EVT:
+ return "BTA_OPS_OBX_CLOSE_EVT";
+ case BTA_OPS_OBX_PUT_EVT:
+ return "BTA_OPS_OBX_PUT_EVT";
+ case BTA_OPS_OBX_GET_EVT:
+ return "BTA_OPS_OBX_GET_EVT";
+ case BTA_OPS_CLOSE_CMPL_EVT:
+ return "BTA_OPS_CLOSE_CMPL_EVT";
+ case BTA_OPS_API_ENABLE_EVT:
+ return "BTA_OPS_API_ENABLE_EVT";
+ default:
+ return "unknown OPS event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function ops_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *ops_state_code(tBTA_OPS_STATE state_code)
+{
+ switch(state_code)
+ {
+ case BTA_OPS_IDLE_ST:
+ return "BTA_OPS_IDLE_ST";
+ case BTA_OPS_LISTEN_ST:
+ return "BTA_OPS_LISTEN_ST";
+ case BTA_OPS_CONN_ST:
+ return "BTA_OPS_CONN_ST";
+ case BTA_OPS_CLOSING_ST:
+ return "BTA_OPS_CLOSING_ST";
+ default:
+ return "unknown OPS state code";
+ }
+}
+
+#endif /* Debug Functions */
+#endif /* BTA_OP_INCLUDED */
diff --git a/bta/op/bta_ops_utils.c b/bta/op/bta_ops_utils.c
new file mode 100644
index 0000000..eccc1e7
--- /dev/null
+++ b/bta/op/bta_ops_utils.c
@@ -0,0 +1,487 @@
+/*****************************************************************************
+**
+** Name: bta_ops_utils.c
+**
+** Description: This file implements object store functions for the
+** object transfer server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_OP_INCLUDED) && (BTA_OP_INCLUDED)
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "bta_fs_api.h"
+#include "bta_ops_int.h"
+#include "bta_fs_co.h"
+#include "gki.h"
+#include "utl.h"
+#include "bd.h"
+
+/*******************************************************************************
+** Constants
+*******************************************************************************/
+
+/*******************************************************************************
+** Local Function Prototypes
+*******************************************************************************/
+static int bta_ops_stricmp (const char *p_str1, const char *p_str2);
+
+/*******************************************************************************
+* Exported Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ops_init_get_obj
+**
+** Description Processes a begin object pull request.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_init_get_obj(tBTA_OPS_CB *p_cb, tBTA_OPS_DATA *p_data)
+{
+ tBTA_OPS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_FORBIDDEN;
+ UINT16 len;
+ UINT8 *p_type;
+ UINT16 name_len;
+
+ /* Type Hdr must be present */
+ if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len))
+ {
+ /* Type Hdr must be correct */
+ if (!bta_ops_stricmp((const char *)p_type, "text/x-vcard"))
+ {
+ /* Erratum 385 - original OPP spec says "Name Header must not be used."
+ * errara says "Name Header must be empty"
+ * Be a forgiving OPP server, allow either way */
+ name_len = OBX_ReadHdrLen(p_evt->p_pkt, OBX_HI_NAME);
+ if((name_len == OBX_INVALID_HDR_LEN) ||/* no name header */
+ (name_len == 3) /* name header is empty */ )
+ {
+ p_cb->obx.p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /*p_cb->peer_mtu*/OBX_CMD_POOL_SIZE);
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1));
+
+ if (p_cb->p_path && p_cb->obx.p_pkt)
+ {
+ p_cb->p_path[0] = '\0';
+ p_cb->p_name = p_cb->p_path;
+ p_cb->obx_oper = OPS_OP_PULL_OBJ;
+ p_cb->obj_fmt = BTA_OP_VCARD21_FMT;
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+
+ /* Notify the appl that a pull default card has been requested */
+ bta_ops_req_app_access (BTA_OP_OPER_PULL, p_cb);
+ rsp_code = OBX_RSP_CONTINUE;
+ }
+ else
+ rsp_code = OBX_RSP_INTRNL_SRVR_ERR;
+ }
+ }
+ }
+
+ /* Error has been detected; respond with error code */
+ if (rsp_code != OBX_RSP_CONTINUE)
+ {
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+ utl_freebuf((void**)&p_cb->p_path);
+ p_cb->p_name = NULL;
+ OBX_GetRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_proc_get_obj
+**
+** Description Processes a continuation packet for pulling a vcard.
+** Builds a response packet and initiates a read into it.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_proc_get_obj(tBTA_OPS_CB *p_cb)
+{
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+
+ /* Allocate a new OBX packet */
+ if ((p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /*p_cb->peer_mtu*/OBX_LRG_DATA_POOL_SIZE)) != NULL)
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ p_cb->cout_active = TRUE;
+ bta_fs_co_read(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_OPS_CI_READ_EVT, 0, p_cb->app_id);
+ }
+ else
+ bta_ops_get_obj_rsp(OBX_RSP_INTRNL_SRVR_ERR, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_proc_put_obj
+**
+** Description Processes a Push Object Operation.
+** Initiates the opening of an object for writing, or continues
+** with a new Obx packet of data (continuation).
+**
+** Parameters p_pkt - Pointer to the OBX Put request
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_proc_put_obj(BT_HDR *p_pkt)
+{
+ tBTA_OPS_CB *p_cb = &bta_ops_cb;
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 num_hdrs;
+ BOOLEAN endpkt;
+
+ p_obx->p_pkt = p_pkt;
+
+ p_obx->offset = 0; /* Initial offset into OBX data */
+ /* Read in start of body if there is a body header */
+ num_hdrs = OBX_ReadBodyHdr(p_obx->p_pkt, &p_obx->p_start, &p_obx->bytes_left,
+ &endpkt);
+ if (num_hdrs == 1)
+ {
+ p_cb->cout_active = TRUE;
+ bta_fs_co_write(p_cb->fd, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left, BTA_OPS_CI_WRITE_EVT, 0, p_cb->app_id);
+ }
+ else
+ {
+ bta_ops_clean_getput(p_cb, TRUE);
+ bta_ops_put_obj_rsp(OBX_RSP_BAD_REQUEST);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_get_obj_rsp
+**
+** Description Finishes up the end body of the object get, and sends out the
+** OBX response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_get_obj_rsp(UINT8 rsp_code, UINT16 num_read)
+{
+ tBTA_OPS_CB *p_cb = &bta_ops_cb;
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_OPS_PROGRESS param;
+ BOOLEAN done = TRUE;
+
+ /* Send the response packet if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ p_obx->offset += num_read;
+
+ /* More to be sent */
+ if (rsp_code == OBX_RSP_CONTINUE)
+ {
+ if (p_obx->bytes_left != num_read)
+ APPL_TRACE_WARNING2("OPS Read: Requested (0x%04x), Read In (0x%04x)",
+ p_obx->bytes_left, num_read);
+ done = FALSE;
+ }
+
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, done);
+
+ /* Notify application with progress */
+ if (num_read)
+ {
+ param.bytes = num_read;
+ param.obj_size = p_cb->file_length;
+ param.operation = BTA_OP_OPER_PULL;
+ p_cb->p_cback(BTA_OPS_PROGRESS_EVT, (tBTA_OPS *)&param);
+ }
+ }
+ else
+ p_cb->obx_oper = OPS_OP_NONE;
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+
+ /* Final response packet sent out */
+ if (done)
+ bta_ops_clean_getput(p_cb, FALSE);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_put_obj_rsp
+**
+** Description Responds to a put request, and closes the object if finished
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_put_obj_rsp(UINT8 rsp_code)
+{
+ tBTA_OPS_CB *p_cb = &bta_ops_cb;
+ tBTA_OPS_OBX_PKT *p_obx = &p_cb->obx;
+ tBTA_OPS_PROGRESS param;
+ tBTA_OPS_OBJECT object;
+
+ /* Finished with input packet */
+ utl_freebuf((void**)&p_obx->p_pkt);
+
+ if (rsp_code == OBX_RSP_OK)
+ {
+ /* Update application if object data was transferred */
+ if (p_obx->bytes_left)
+ {
+ param.bytes = p_obx->bytes_left;
+ param.obj_size = p_cb->file_length;
+ param.operation = BTA_OP_OPER_PUSH;
+ p_cb->p_cback(BTA_OPS_PROGRESS_EVT, (tBTA_OPS *)&param);
+ }
+
+ /* If not end of object put, set the continue response */
+ if (!p_obx->final_pkt)
+ rsp_code = OBX_RSP_CONTINUE;
+ else /* Done - free the allocated memory */
+ {
+ /* callback to app with object */
+ object.format = p_cb->obj_fmt;
+ object.p_name = p_cb->p_name;
+
+ bta_ops_clean_getput(p_cb, FALSE);
+ p_cb->p_cback(BTA_OPS_OBJECT_EVT, (tBTA_OPS *) &object);
+
+ }
+ }
+ else
+ p_cb->obx_oper = OPS_OP_NONE;
+
+ OBX_PutRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_req_app_access
+**
+** Description Sends an access request event to the application.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_req_app_access (tBTA_OP_OPER oper, tBTA_OPS_CB *p_cb)
+{
+ tBTA_OPS_ACCESS *p_acc_evt;
+ char *p_devname;
+ UINT16 len;
+
+ /* Notify the application that a put or get file has been requested */
+ if ((p_acc_evt = (tBTA_OPS_ACCESS *)GKI_getbuf(sizeof(tBTA_OPS_ACCESS))) != NULL)
+ {
+ memset(p_acc_evt, 0, sizeof(tBTA_OPS_ACCESS));
+ p_acc_evt->p_name = p_cb->p_name;
+ p_acc_evt->size = p_cb->file_length;
+ p_acc_evt->oper = p_cb->acc_active = oper;
+ p_acc_evt->format = p_cb->obj_fmt;
+ bdcpy(p_acc_evt->bd_addr, p_cb->bd_addr);
+
+ if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL)
+ BCM_STRNCPY_S((char *)p_acc_evt->dev_name, sizeof(tBTM_BD_NAME), p_devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ /* Only pass the object type if Push operation */
+ if (oper == BTA_OP_OPER_PUSH)
+ {
+ if (!OBX_ReadTypeHdr(p_cb->obx.p_pkt, (UINT8 **)&p_acc_evt->p_type, &len))
+ p_acc_evt->p_type = NULL;
+ }
+
+ if (p_acc_evt->p_type)
+ {
+ APPL_TRACE_EVENT3("OPS Access Request...Name [%s], Oper [%d], Type [%s]",
+ p_cb->p_name, oper, p_acc_evt->p_type);
+ }
+ else
+ {
+ APPL_TRACE_EVENT2("OPS Access Request...Name [%s], Oper [%d]",
+ p_cb->p_name, oper);
+ }
+
+ p_cb->p_cback(BTA_OPS_ACCESS_EVT, (tBTA_OPS *)p_acc_evt);
+ GKI_freebuf(p_acc_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_clean_getput
+**
+** Description Cleans up the get/put resources and control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_clean_getput(tBTA_OPS_CB *p_cb, BOOLEAN is_aborted)
+{
+ tBTA_FS_CO_STATUS status;
+
+ /* Clean up control block */
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_fs_co_close(p_cb->fd, p_cb->app_id);
+ p_cb->fd = BTA_FS_INVALID_FD;
+
+ /* Delete an aborted unfinished push file operation */
+ if (is_aborted && p_cb->obx_oper == OPS_OP_PUSH_OBJ)
+ {
+ status = bta_fs_co_unlink(p_cb->p_path, p_cb->app_id);
+ APPL_TRACE_WARNING2("OPS: Remove ABORTED Push File Operation [%s], status 0x%02x", p_cb->p_path, status);
+ }
+ }
+
+ utl_freebuf((void**)&p_cb->p_path);
+ p_cb->p_name = NULL;
+
+ p_cb->obx_oper = OPS_OP_NONE;
+ p_cb->obx.bytes_left = 0;
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+ p_cb->acc_active = 0;
+ p_cb->aborting = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_fmt_supported
+**
+** Description This function determines the file type from a file name
+** and checks if the file type is supported.
+**
+**
+** Returns Format type value or zero if format unsupported.
+**
+*******************************************************************************/
+tBTA_OP_FMT bta_ops_fmt_supported(char *p, tBTA_OP_FMT_MASK fmt_mask)
+{
+ char *p_suffix;
+ tBTA_OP_FMT fmt = BTA_OP_OTHER_FMT;
+
+ /* scan to find file suffix */
+ if ((p_suffix = strrchr(p, '.')) != NULL)
+ {
+ p_suffix++;
+ if (bta_ops_stricmp (p_suffix, "vcf") == 0)
+ {
+ fmt = BTA_OP_VCARD21_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "vcd") == 0)
+ {
+ fmt = BTA_OP_VCARD30_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "vcs") == 0)
+ {
+ fmt = BTA_OP_VCAL_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "ics") == 0)
+ {
+ fmt = BTA_OP_ICAL_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "vmg") == 0)
+ {
+ fmt = BTA_OP_VMSG_FMT;
+ }
+ else if (bta_ops_stricmp (p_suffix, "vnt") == 0)
+ {
+ fmt = BTA_OP_VNOTE_FMT;
+ }
+ }
+
+ /* see if supported */
+ if (fmt == BTA_OP_OTHER_FMT)
+ {
+ if (!(fmt_mask & BTA_OP_ANY_MASK))
+ fmt = 0; /* Other types not supported */
+ }
+ else
+ {
+ if (!((1 << (fmt - 1)) & fmt_mask))
+ fmt = 0;
+ }
+
+ return fmt;
+}
+
+/*******************************************************************************
+**
+** Function bta_ops_discard_data
+**
+** Description frees the data
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ops_discard_data(UINT16 event, tBTA_OPS_DATA *p_data)
+{
+ switch(event)
+ {
+ case BTA_OPS_OBX_CONN_EVT:
+ case BTA_OPS_OBX_DISC_EVT:
+ case BTA_OPS_OBX_ABORT_EVT:
+ case BTA_OPS_OBX_CLOSE_EVT:
+ case BTA_OPS_OBX_PUT_EVT:
+ case BTA_OPS_OBX_GET_EVT:
+ utl_freebuf((void**)&p_data->obx_evt.p_pkt);
+ break;
+
+ default:
+ /*Nothing to free*/
+ break;
+ }
+}
+
+/*******************************************************************************
+* Static Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_ops_stricmp
+**
+** Description Used to compare type header
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static int bta_ops_stricmp (const char *p_str1, const char *p_str2)
+{
+ UINT16 i;
+ UINT16 cmplen;
+
+ if (!p_str1 || !p_str2)
+ return (1);
+
+ cmplen = strlen(p_str1);
+ if (cmplen != strlen(p_str2))
+ return (1);
+
+ for (i = 0; i < cmplen; i++)
+ {
+ if (toupper(p_str1[i]) != toupper(p_str2[i]))
+ return (i+1);
+ }
+
+ return 0;
+}
+#endif /* BTA_OP_INCLUDED */
diff --git a/bta/pan/bta_pan_act.c b/bta/pan/bta_pan_act.c
new file mode 100644
index 0000000..d9424ec
--- /dev/null
+++ b/bta/pan/bta_pan_act.c
@@ -0,0 +1,718 @@
+/*****************************************************************************
+**
+** Name: bta_pan_act.c
+**
+** Description: This file contains the pan action functions
+** for the state machine.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(PAN_INCLUDED) && (PAN_INCLUDED == TRUE)
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bd.h"
+#include "gki.h"
+#include "pan_api.h"
+#include "bta_pan_api.h"
+#include "bta_pan_int.h"
+#include "bta_pan_co.h"
+#include <string.h>
+
+
+/* RX and TX data flow mask */
+#define BTA_PAN_RX_MASK 0x0F
+#define BTA_PAN_TX_MASK 0xF0
+
+/*******************************************************************************
+**
+** Function bta_pan_conn_state_cback
+**
+** Description Connection state callback from Pan profile
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_conn_state_cback(UINT16 handle, BD_ADDR bd_addr, tPAN_RESULT state,
+ BOOLEAN is_role_change, UINT8 src_role, UINT8 dst_role)
+{
+
+ tBTA_PAN_CONN * p_buf;
+ tBTA_PAN_SCB *p_scb;
+
+
+ if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL)
+ {
+ if((state == PAN_SUCCESS) && !is_role_change)
+ {
+ p_buf->hdr.event = BTA_PAN_CONN_OPEN_EVT;
+ if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
+ {
+ /* allocate an scb */
+ p_scb = bta_pan_scb_alloc();
+
+ }
+ /* we have exceeded maximum number of connections */
+ if(!p_scb)
+ {
+ PAN_Disconnect (handle);
+ return;
+ }
+
+ p_scb->handle = handle;
+ p_scb->local_role = src_role;
+ p_scb->peer_role = dst_role;
+ p_scb->pan_flow_enable = TRUE;
+ bdcpy(p_scb->bd_addr, bd_addr);
+ GKI_init_q(&p_scb->data_queue);
+
+ if(src_role == PAN_ROLE_CLIENT)
+ p_scb->app_id = bta_pan_cb.app_id[0];
+ else if (src_role == PAN_ROLE_GN_SERVER)
+ p_scb->app_id = bta_pan_cb.app_id[1];
+ else if (src_role == PAN_ROLE_NAP_SERVER)
+ p_scb->app_id = bta_pan_cb.app_id[2];
+
+ }
+ else if((state != PAN_SUCCESS) && !is_role_change)
+ {
+ p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT;
+
+ }
+ else
+ {
+ return;
+ }
+
+ p_buf->result = state;
+ p_buf->hdr.layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+
+ }
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_data_flow_cb
+**
+** Description Data flow status callback from PAN
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_data_flow_cb(UINT16 handle, tPAN_RESULT result)
+{
+ BT_HDR *p_buf;
+ tBTA_PAN_SCB *p_scb;
+
+ if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
+ return;
+
+ if(result == PAN_TX_FLOW_ON)
+ {
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->layer_specific = handle;
+ p_buf->event = BTA_PAN_BNEP_FLOW_ENABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+ bta_pan_co_rx_flow(handle, p_scb->app_id, TRUE);
+
+ }
+ else if(result == PAN_TX_FLOW_OFF)
+ {
+
+ p_scb->pan_flow_enable = FALSE;
+ bta_pan_co_rx_flow(handle, p_scb->app_id, FALSE);
+
+ }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_data_buf_ind_cback
+**
+** Description data indication callback from pan profile
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_data_buf_ind_cback(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf,
+ BOOLEAN ext, BOOLEAN forward)
+{
+ tBTA_PAN_SCB *p_scb;
+ BT_HDR * p_event;
+ BT_HDR *p_new_buf;
+
+ if ( sizeof(tBTA_PAN_DATA_PARAMS) > p_buf->offset )
+ {
+ /* offset smaller than data structure in front of actual data */
+ p_new_buf = (BT_HDR *)GKI_getpoolbuf( PAN_POOL_ID );
+ if(!p_new_buf)
+ {
+ APPL_TRACE_WARNING0("Cannot get a PAN GKI buffer");
+ GKI_freebuf( p_buf );
+ return;
+ }
+ else
+ {
+ memcpy( (UINT8 *)(p_new_buf+1)+sizeof(tBTA_PAN_DATA_PARAMS), (UINT8 *)(p_buf+1)+p_buf->offset, p_buf->len );
+ p_new_buf->len = p_buf->len;
+ p_new_buf->offset = sizeof(tBTA_PAN_DATA_PARAMS);
+ GKI_freebuf( p_buf );
+ }
+ }
+ else
+ {
+ p_new_buf = p_buf;
+ }
+ /* copy params into the space before the data */
+ bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->src, src);
+ bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->dst, dst);
+ ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->protocol = protocol;
+ ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->ext = ext;
+ ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->forward = forward;
+
+
+ if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
+ {
+
+ GKI_freebuf( p_new_buf );
+ return;
+ }
+
+ GKI_enqueue(&p_scb->data_queue, p_new_buf);
+ if ((p_event = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_event->layer_specific = handle;
+ p_event->event = BTA_PAN_RX_FROM_BNEP_READY_EVT;
+ bta_sys_sendmsg(p_event);
+ }
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_pfilt_ind_cback
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_pfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result,
+ UINT16 num_filters, UINT8 *p_filters)
+{
+
+ bta_pan_co_pfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL),
+ num_filters, p_filters);
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_mfilt_ind_cback
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_mfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result,
+ UINT16 num_mfilters, UINT8 *p_mfilters)
+{
+
+ bta_pan_co_mfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL),
+ num_mfilters, p_mfilters);
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_pan_enable
+**
+** Description
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_enable(tBTA_PAN_DATA *p_data)
+{
+ tPAN_REGISTER reg_data;
+ UINT16 initial_discoverability;
+ UINT16 initial_connectability;
+ UINT16 d_window;
+ UINT16 d_interval;
+ UINT16 c_window;
+ UINT16 c_interval;
+
+ bta_pan_cb.p_cback = p_data->api_enable.p_cback;
+
+ reg_data.pan_conn_state_cb = bta_pan_conn_state_cback;
+ reg_data.pan_bridge_req_cb = NULL;
+ reg_data.pan_data_buf_ind_cb = bta_pan_data_buf_ind_cback;
+ reg_data.pan_data_ind_cb = NULL;
+ reg_data.pan_pfilt_ind_cb = bta_pan_pfilt_ind_cback;
+ reg_data.pan_mfilt_ind_cb = bta_pan_mfilt_ind_cback;
+ reg_data.pan_tx_data_flow_cb = bta_pan_data_flow_cb;
+
+ /* read connectability and discoverability settings.
+ Pan profile changes the settings. We have to change it back to
+ be consistent with other bta subsystems */
+ initial_connectability = BTM_ReadConnectability(&c_window, &c_interval);
+ initial_discoverability = BTM_ReadDiscoverability(&d_window, &d_interval);
+
+
+ PAN_Register (&reg_data);
+
+
+ /* set it back to original value */
+ BTM_SetDiscoverability(initial_discoverability, d_window, d_interval);
+ BTM_SetConnectability(initial_connectability, c_window, c_interval);
+
+ bta_pan_cb.flow_mask = bta_pan_co_init(&bta_pan_cb.q_level);
+ bta_pan_cb.p_cback(BTA_PAN_ENABLE_EVT, NULL);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_set_role
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_set_role(tBTA_PAN_DATA *p_data)
+{
+ tPAN_RESULT status;
+ tBTA_PAN_SET_ROLE set_role;
+ UINT8 sec[3];
+
+
+ bta_pan_cb.app_id[0] = p_data->api_set_role.user_app_id;
+ bta_pan_cb.app_id[1] = p_data->api_set_role.gn_app_id;
+ bta_pan_cb.app_id[2] = p_data->api_set_role.nap_app_id;
+
+ sec[0] = p_data->api_set_role.user_sec_mask;
+ sec[1] = p_data->api_set_role.gn_sec_mask;
+ sec[2] = p_data->api_set_role.nap_sec_mask;
+
+ /* set security correctly in api and here */
+ status = PAN_SetRole(p_data->api_set_role.role, sec,
+ p_data->api_set_role.user_name,
+ p_data->api_set_role.gn_name,
+ p_data->api_set_role.nap_name);
+
+ if(status == PAN_SUCCESS)
+ {
+ if(p_data->api_set_role.role & PAN_ROLE_NAP_SERVER )
+ bta_sys_add_uuid(UUID_SERVCLASS_NAP);
+ else
+ bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
+
+ if(p_data->api_set_role.role & PAN_ROLE_GN_SERVER )
+ bta_sys_add_uuid(UUID_SERVCLASS_GN);
+ else
+ bta_sys_remove_uuid(UUID_SERVCLASS_GN);
+
+ if(p_data->api_set_role.role & PAN_ROLE_CLIENT )
+ bta_sys_add_uuid(UUID_SERVCLASS_PANU);
+ else
+ bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
+
+ set_role.role = p_data->api_set_role.role;
+ bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role);
+ }
+ /* if status is not success clear everything */
+ else
+ {
+ PAN_SetRole(0, 0, NULL, NULL, NULL);
+
+ bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
+ bta_sys_remove_uuid(UUID_SERVCLASS_GN);
+ bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
+ set_role.role = 0;
+ bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role);
+ }
+
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_pan_disable
+**
+** Description
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_disable(void)
+{
+
+ BT_HDR *p_buf;
+ tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0];
+ UINT8 i;
+
+
+ /* close all connections */
+ PAN_SetRole (0, NULL, NULL, NULL, NULL);
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+ bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
+ bta_sys_remove_uuid(UUID_SERVCLASS_GN);
+ bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
+#endif
+ /* free all queued up data buffers */
+ for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++)
+ {
+ if (p_scb->in_use)
+ {
+ while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
+ GKI_freebuf(p_buf);
+
+ bta_pan_co_close(p_scb->handle, p_scb->app_id);
+
+ }
+ }
+
+
+
+ PAN_Deregister();
+
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_open
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+ tPAN_RESULT status;
+ tBTA_PAN_OPEN data;
+ tBTA_PAN_OPENING opening;
+
+
+ status = PAN_Connect (p_data->api_open.bd_addr, p_data->api_open.local_role, p_data->api_open.peer_role,
+ &p_scb->handle);
+
+
+ if(status == PAN_SUCCESS)
+ {
+
+ bdcpy(p_scb->bd_addr, p_data->api_open.bd_addr);
+ p_scb->local_role = p_data->api_open.local_role;
+ p_scb->peer_role = p_data->api_open.peer_role;
+ bdcpy(opening.bd_addr, p_data->api_open.bd_addr);
+ opening.handle = p_scb->handle;
+ bta_pan_cb.p_cback(BTA_PAN_OPENING_EVT, (tBTA_PAN *)&opening);
+
+
+ }
+ else
+ {
+ bta_pan_scb_dealloc(p_scb);
+ bdcpy(data.bd_addr, p_data->api_open.bd_addr);
+ data.status = BTA_PAN_FAIL;
+ bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
+ }
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_close
+**
+** Description
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_api_close (tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+ tBTA_PAN_CONN * p_buf;
+
+ PAN_Disconnect (p_scb->handle);
+
+
+ /* send an event to BTA so that application will get the connection
+ close event */
+ if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT;
+
+ p_buf->hdr.layer_specific = p_scb->handle;
+ bta_sys_sendmsg(p_buf);
+
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_conn_open
+**
+** Description process connection open event
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+
+ tBTA_PAN_OPEN data;
+
+ bdcpy(data.bd_addr, p_scb->bd_addr);
+ data.handle = p_scb->handle;
+ data.local_role = p_scb->local_role;
+ data.peer_role = p_scb->peer_role;
+
+ if(p_data->conn.result == PAN_SUCCESS)
+ {
+ data.status = BTA_PAN_SUCCESS;
+ bta_pan_co_open(p_scb->handle, p_scb->app_id, p_scb->local_role, p_scb->peer_role, p_scb->bd_addr);
+
+ }
+ else
+ {
+ bta_pan_scb_dealloc(p_scb);
+ data.status = BTA_PAN_FAIL;
+ }
+
+ p_scb->pan_flow_enable = TRUE;
+ p_scb->app_flow_enable = TRUE;
+
+ bta_sys_conn_open( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
+
+ bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_conn_close
+**
+** Description process connection close event
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+
+ tBTA_PAN_CLOSE data;
+ BT_HDR *p_buf;
+
+ data.handle = p_data->hdr.layer_specific;
+
+
+ bta_sys_conn_close( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
+
+ /* free all queued up data buffers */
+ while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
+ GKI_freebuf(p_buf);
+
+ GKI_init_q(&p_scb->data_queue);
+
+ bta_pan_co_close(p_scb->handle, p_scb->app_id);
+
+ bta_pan_scb_dealloc(p_scb);
+
+ bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, (tBTA_PAN *)&data);
+
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_pan_rx_path
+**
+** Description Handle data on the RX path (data sent from the phone to
+** BTA).
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+ /* if data path configured for rx pull */
+ if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PULL)
+ {
+ /* if we can accept data */
+ if (p_scb->pan_flow_enable == TRUE)
+ {
+ /* call application callout function for rx path */
+ bta_pan_co_rx_path(p_scb->handle, p_scb->app_id);
+ }
+ }
+ /* else data path configured for rx push */
+ else
+ {
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_tx_path
+**
+** Description Handle the TX data path (data sent from BTA to the phone).
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+
+ BT_HDR * p_buf;
+ /* if data path configured for tx pull */
+ if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PULL)
+ {
+ /* call application callout function for tx path */
+ bta_pan_co_tx_path(p_scb->handle, p_scb->app_id);
+
+ /* free data that exceeds queue level */
+ while(p_scb->data_queue.count > bta_pan_cb.q_level)
+ GKI_freebuf(GKI_dequeue(&p_scb->data_queue));
+ }
+ /* if configured for zero copy push */
+ else if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PUSH_BUF)
+ {
+ /* if app can accept data */
+ if (p_scb->app_flow_enable == TRUE)
+ {
+ /* read data from the queue */
+ if ((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
+ {
+ /* send data to application */
+ bta_pan_co_tx_writebuf(p_scb->handle,
+ p_scb->app_id,
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->src,
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->dst,
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol,
+ p_buf,
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext,
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward);
+
+ }
+ /* free data that exceeds queue level */
+ while(p_scb->data_queue.count > bta_pan_cb.q_level)
+ GKI_freebuf(GKI_dequeue(&p_scb->data_queue));
+
+ /* if there is more data to be passed to
+ upper layer */
+ if(p_scb->data_queue.count)
+ {
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->layer_specific = p_scb->handle;
+ p_buf->event = BTA_PAN_RX_FROM_BNEP_READY_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+
+ }
+
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_tx_flow
+**
+** Description Set the application flow control state.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+ p_scb->app_flow_enable = p_data->ci_tx_flow.enable;
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_write_buf
+**
+** Description Handle a bta_pan_ci_rx_writebuf() and send data to PAN.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+ if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PUSH_BUF)
+ {
+
+ PAN_WriteBuf (p_scb->handle,
+ ((tBTA_PAN_DATA_PARAMS *)p_data)->dst,
+ ((tBTA_PAN_DATA_PARAMS *)p_data)->src,
+ ((tBTA_PAN_DATA_PARAMS *)p_data)->protocol,
+ (BT_HDR *)p_data,
+ ((tBTA_PAN_DATA_PARAMS *)p_data)->ext);
+
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_free_buf
+**
+** Description Frees the data buffer during closing state
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+
+ GKI_freebuf(p_data);
+
+}
+
+#endif /* PAN_INCLUDED */
diff --git a/bta/pan/bta_pan_api.c b/bta/pan/bta_pan_api.c
new file mode 100644
index 0000000..5a84668
--- /dev/null
+++ b/bta/pan/bta_pan_api.c
@@ -0,0 +1,202 @@
+/*****************************************************************************
+**
+** Name: bta_pan_api.c
+**
+** Description: This is the implementation of the API for PAN
+** subsystem of BTA, Widcomm's Bluetooth application
+** layer for mobile phones.
+**
+** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE)
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "pan_api.h"
+#include "gki.h"
+#include "bta_pan_api.h"
+#include "bta_pan_int.h"
+#include "bd.h"
+#include <string.h>
+
+static const tBTA_SYS_REG bta_pan_reg =
+{
+ bta_pan_hdl_event,
+ BTA_PanDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_PanEnable
+**
+** Description Enable PAN service. This function must be
+** called before any other functions in the PAN API are called.
+** When the enable operation is complete the callback function
+** will be called with a BTA_PAN_ENABLE_EVT.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PanEnable(tBTA_PAN_CBACK p_cback)
+{
+ tBTA_PAN_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_PAN, &bta_pan_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_PAN_API_ENABLE *) GKI_getbuf(sizeof(tBTA_PAN_API_ENABLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_PAN_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+
+
+/*******************************************************************************
+**
+** Function BTA_PanDisable
+**
+** Description Disables PAN service.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PanDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_PAN);
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_PAN_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_PanSetRole
+**
+** Description Sets PAN roles. When the enable operation is complete
+** the callback function will be called with a BTA_PAN_SET_ROLE_EVT.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PanSetRole(tBTA_PAN_ROLE role, tBTA_PAN_ROLE_INFO *p_user_info, tBTA_PAN_ROLE_INFO *p_gn_info,
+ tBTA_PAN_ROLE_INFO *p_nap_info)
+{
+
+ tBTA_PAN_API_SET_ROLE *p_buf;
+
+ if ((p_buf = (tBTA_PAN_API_SET_ROLE *) GKI_getbuf(sizeof(tBTA_PAN_API_SET_ROLE))) != NULL)
+ {
+ p_buf->hdr.event = BTA_PAN_API_SET_ROLE_EVT;
+ p_buf->role = role;
+
+ if(p_user_info && (role & BTA_PAN_ROLE_PANU))
+ {
+ if(p_user_info->p_srv_name)
+ BCM_STRNCPY_S(p_buf->user_name, sizeof(p_buf->user_name), p_user_info->p_srv_name, BTA_SERVICE_NAME_LEN);
+ else
+ p_buf->user_name[0] = 0;
+
+ p_buf->user_name[BTA_SERVICE_NAME_LEN] = 0;
+ p_buf->user_app_id = p_user_info->app_id;
+ p_buf->user_sec_mask = p_user_info->sec_mask;
+ }
+
+ if(p_gn_info && (role & BTA_PAN_ROLE_GN))
+ {
+ if(p_gn_info->p_srv_name)
+ BCM_STRNCPY_S(p_buf->gn_name, sizeof(p_buf->gn_name), p_gn_info->p_srv_name, BTA_SERVICE_NAME_LEN);
+ else
+ p_buf->gn_name[0] = 0;
+
+ p_buf->gn_name[BTA_SERVICE_NAME_LEN] = 0;
+ p_buf->gn_app_id = p_gn_info->app_id;
+ p_buf->gn_sec_mask = p_gn_info->sec_mask;
+
+ }
+
+ if(p_nap_info && (role & BTA_PAN_ROLE_NAP))
+ {
+ if(p_nap_info->p_srv_name)
+ BCM_STRNCPY_S(p_buf->nap_name, sizeof(p_buf->nap_name), p_nap_info->p_srv_name, BTA_SERVICE_NAME_LEN);
+ else
+ p_buf->nap_name[0] = 0;
+
+ p_buf->nap_name[BTA_SERVICE_NAME_LEN] = 0;
+ p_buf->nap_app_id = p_nap_info->app_id;
+ p_buf->nap_sec_mask = p_nap_info->sec_mask;
+
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_PanOpen
+**
+** Description Opens a connection to a peer device.
+** When connection is open callback function is called
+** with a BTA_PAN_OPEN_EVT.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_PanOpen(BD_ADDR bd_addr, tBTA_PAN_ROLE local_role, tBTA_PAN_ROLE peer_role)
+{
+
+ tBTA_PAN_API_OPEN *p_buf;
+
+ if ((p_buf = (tBTA_PAN_API_OPEN *) GKI_getbuf(sizeof(tBTA_PAN_API_OPEN))) != NULL)
+ {
+ p_buf->hdr.event = BTA_PAN_API_OPEN_EVT;
+ p_buf->local_role = local_role;
+ p_buf->peer_role = peer_role;
+ bdcpy(p_buf->bd_addr, bd_addr);
+ bta_sys_sendmsg(p_buf);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function BTA_PanClose
+**
+** Description Close a PAN connection to a peer device.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API void BTA_PanClose(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_PAN_API_CLOSE_EVT;
+ p_buf->layer_specific = handle;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+#endif /* BTA_PAN_INCLUDED */
diff --git a/bta/pan/bta_pan_ci.c b/bta/pan/bta_pan_ci.c
new file mode 100644
index 0000000..843d2b9
--- /dev/null
+++ b/bta/pan/bta_pan_ci.c
@@ -0,0 +1,248 @@
+/*****************************************************************************
+**
+** Name: bta_pan_ci.c
+**
+** Description: This is the implementation file for data gateway call-in
+** functions.
+**
+** Copyright (c) 2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "gki.h"
+#include "pan_api.h"
+#include "bd.h"
+#include "bta_api.h"
+#include "bta_pan_api.h"
+#include "bta_pan_ci.h"
+#include "bta_pan_int.h"
+
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_tx_ready
+**
+** Description This function sends an event to PAN indicating the phone is
+** ready for more data and PAN should call bta_pan_co_tx_path().
+** This function is used when the TX data path is configured
+** to use a pull interface.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_ci_tx_ready(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->layer_specific = handle;
+ p_buf->event = BTA_PAN_CI_TX_READY_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_rx_ready
+**
+** Description This function sends an event to PAN indicating the phone
+** has data available to send to PAN and PAN should call
+** bta_pan_co_rx_path(). This function is used when the RX
+** data path is configured to use a pull interface.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_ci_rx_ready(UINT16 handle)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->layer_specific = handle;
+ p_buf->event = BTA_PAN_CI_RX_READY_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_tx_flow
+**
+** Description This function is called to enable or disable data flow on
+** the TX path. The phone should call this function to
+** disable data flow when it is congested and cannot handle
+** any more data sent by bta_pan_co_tx_write() or
+** bta_pan_co_tx_writebuf(). This function is used when the
+** TX data path is configured to use a push interface.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_ci_tx_flow(UINT16 handle, BOOLEAN enable)
+{
+ tBTA_PAN_CI_TX_FLOW *p_buf;
+
+ if ((p_buf = (tBTA_PAN_CI_TX_FLOW *) GKI_getbuf(sizeof(tBTA_PAN_CI_TX_FLOW))) != NULL)
+ {
+ p_buf->hdr.layer_specific = handle;
+ p_buf->hdr.event = BTA_PAN_CI_TX_FLOW_EVT;
+ p_buf->enable = enable;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_rx_write
+**
+** Description This function is called to send data to PAN when the RX path
+** is configured to use a push interface. The function copies
+** data to an event buffer and sends it to PAN.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_ci_rx_write(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol,
+ UINT8 *p_data, UINT16 len, BOOLEAN ext)
+{
+ BT_HDR * p_buf;
+
+ if((p_buf = (BT_HDR *) GKI_getpoolbuf(PAN_POOL_ID)) != NULL)
+ {
+
+
+ p_buf->offset = PAN_MINIMUM_OFFSET;
+
+ /* copy all other params before the data */
+ bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->src, src);
+ bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, dst);
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol = protocol;
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext = ext;
+ p_buf->len=len;
+
+ /* copy data */
+ memcpy((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, len);
+
+ p_buf->layer_specific = handle;
+ p_buf->event = BTA_PAN_CI_RX_WRITEBUF_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_rx_writebuf
+**
+** Description This function is called to send data to the phone when
+** the RX path is configured to use a push interface with
+** zero copy. The function sends an event to PAN containing
+** the data buffer. The buffer must be allocated using
+** functions GKI_getbuf() or GKI_getpoolbuf(). The buffer
+** will be freed by BTA; the phone must not free the buffer.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_ci_rx_writebuf(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol,
+ BT_HDR *p_buf, BOOLEAN ext)
+{
+
+ /* copy all other params before the data */
+ bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->src, src);
+ bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, dst);
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol = protocol;
+ ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext = ext;
+
+ p_buf->layer_specific = handle;
+ p_buf->event = BTA_PAN_CI_RX_WRITEBUF_EVT;
+ bta_sys_sendmsg(p_buf);
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_readbuf
+**
+** Description
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BT_HDR * bta_pan_ci_readbuf(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16* p_protocol,
+ BOOLEAN* p_ext, BOOLEAN* p_forward)
+{
+ tBTA_PAN_SCB * p_scb;
+ BT_HDR * p_buf;
+
+ p_scb = bta_pan_scb_by_handle(handle);
+
+ p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue);
+
+ if(p_buf)
+ {
+ bdcpy(src,((tBTA_PAN_DATA_PARAMS *)p_buf)->src);
+ bdcpy(dst,((tBTA_PAN_DATA_PARAMS *)p_buf)->dst);
+ *p_protocol = ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol;
+ *p_ext = ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext;
+ *p_forward = ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward;
+ }
+
+ return p_buf;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_set_mfilters
+**
+** Description This function is called to set multicast filters
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_ci_set_mfilters(UINT16 handle, UINT16 num_mcast_filters, UINT8 *p_start_array,
+ UINT8 *p_end_array)
+{
+
+ PAN_SetMulticastFilters(handle, num_mcast_filters, p_start_array, p_end_array);
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_ci_set_mfilters
+**
+** Description This function is called to set protocol filters
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_ci_set_pfilters(UINT16 handle, UINT16 num_filters, UINT16 *p_start_array, UINT16 *p_end_array)
+{
+
+ PAN_SetProtocolFilters(handle, num_filters, p_start_array, p_end_array );
+
+}
+
+#endif /* BTA_PAN_API */
diff --git a/bta/pan/bta_pan_int.h b/bta/pan/bta_pan_int.h
new file mode 100644
index 0000000..5715c31
--- /dev/null
+++ b/bta/pan/bta_pan_int.h
@@ -0,0 +1,200 @@
+/*****************************************************************************
+**
+** Name: bta_pan_int.h
+**
+** Description: This is the private interface file for the BTA data
+** gateway.
+**
+** Copyright (c) 2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_PAN_INT_H
+#define BTA_PAN_INT_H
+
+#include "bta_sys.h"
+#include "bta_pan_api.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+
+
+
+/* PAN events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_PAN_API_CLOSE_EVT = BTA_SYS_EVT_START(BTA_ID_PAN),
+ BTA_PAN_CI_TX_READY_EVT,
+ BTA_PAN_CI_RX_READY_EVT,
+ BTA_PAN_CI_TX_FLOW_EVT,
+ BTA_PAN_CI_RX_WRITE_EVT,
+ BTA_PAN_CI_RX_WRITEBUF_EVT,
+ BTA_PAN_CONN_OPEN_EVT,
+ BTA_PAN_CONN_CLOSE_EVT,
+ BTA_PAN_BNEP_FLOW_ENABLE_EVT,
+ BTA_PAN_RX_FROM_BNEP_READY_EVT,
+
+ /* these events are handled outside of the state machine */
+ BTA_PAN_API_ENABLE_EVT,
+ BTA_PAN_API_DISABLE_EVT,
+ BTA_PAN_API_SET_ROLE_EVT,
+ BTA_PAN_API_OPEN_EVT
+};
+
+
+
+
+/*****************************************************************************
+** Data types
+*****************************************************************************/
+
+/* data type for BTA_PAN_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ tBTA_PAN_CBACK *p_cback; /* PAN callback function */
+} tBTA_PAN_API_ENABLE;
+
+/* data type for BTA_PAN_API_REG_ROLE_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ char user_name[BTA_SERVICE_NAME_LEN+1]; /* Service name */
+ char gn_name[BTA_SERVICE_NAME_LEN+1]; /* Service name */
+ char nap_name[BTA_SERVICE_NAME_LEN+1]; /* Service name */
+ tBTA_PAN_ROLE role;
+ UINT8 user_app_id;
+ UINT8 gn_app_id;
+ UINT8 nap_app_id;
+ tBTA_SEC user_sec_mask; /* Security mask */
+ tBTA_SEC gn_sec_mask; /* Security mask */
+ tBTA_SEC nap_sec_mask; /* Security mask */
+
+
+} tBTA_PAN_API_SET_ROLE;
+
+/* data type for BTA_PAN_API_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ tBTA_PAN_ROLE local_role; /* local role */
+ tBTA_PAN_ROLE peer_role; /* peer role */
+ BD_ADDR bd_addr; /* peer bdaddr */
+} tBTA_PAN_API_OPEN;
+
+/* data type for BTA_PAN_CI_TX_FLOW_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ BOOLEAN enable; /* Flow control setting */
+} tBTA_PAN_CI_TX_FLOW;
+
+/* data type for BTA_PAN_CONN_OPEN_EVT */
+typedef struct
+{
+ BT_HDR hdr; /* Event header */
+ tPAN_RESULT result;
+
+} tBTA_PAN_CONN;
+
+
+
+
+/* union of all data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_PAN_API_ENABLE api_enable;
+ tBTA_PAN_API_SET_ROLE api_set_role;
+ tBTA_PAN_API_OPEN api_open;
+ tBTA_PAN_CI_TX_FLOW ci_tx_flow;
+ tBTA_PAN_CONN conn;
+} tBTA_PAN_DATA;
+
+/* state machine control block */
+typedef struct
+{
+ BD_ADDR bd_addr; /* peer bdaddr */
+ BUFFER_Q data_queue; /* Queue of buffers waiting to be passed to application */
+ UINT16 handle; /* BTA PAN/BNEP handle */
+ BOOLEAN in_use; /* scb in use */
+ tBTA_SEC sec_mask; /* Security mask */
+ BOOLEAN pan_flow_enable;/* BNEP flow control state */
+ BOOLEAN app_flow_enable;/* Application flow control state */
+ UINT8 state; /* State machine state */
+ tBTA_PAN_ROLE local_role; /* local role */
+ tBTA_PAN_ROLE peer_role; /* peer role */
+ UINT8 app_id; /* application id for the connection */
+
+} tBTA_PAN_SCB;
+
+
+
+/* main control block */
+typedef struct
+{
+ tBTA_PAN_SCB scb[BTA_PAN_NUM_CONN]; /* state machine control blocks */
+ tBTA_PAN_CBACK *p_cback; /* PAN callback function */
+ UINT8 app_id[3]; /* application id for PAN roles */
+ UINT8 flow_mask; /* Data flow mask */
+ UINT8 q_level; /* queue level set by application for TX data */
+
+} tBTA_PAN_CB;
+
+
+/* pan data param */
+typedef struct
+{
+ BT_HDR hdr;
+ BD_ADDR src;
+ BD_ADDR dst;
+ UINT16 protocol;
+ BOOLEAN ext;
+ BOOLEAN forward;
+
+} tBTA_PAN_DATA_PARAMS;
+
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* PAN control block */
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_PAN_CB bta_pan_cb;
+#else
+extern tBTA_PAN_CB *bta_pan_cb_ptr;
+#define bta_pan_cb (*bta_pan_cb_ptr)
+#endif
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+extern tBTA_PAN_SCB *bta_pan_scb_alloc(void);
+extern void bta_pan_scb_dealloc(tBTA_PAN_SCB *p_scb);
+extern UINT8 bta_pan_scb_to_idx(tBTA_PAN_SCB *p_scb);
+extern tBTA_PAN_SCB *bta_pan_scb_by_handle(UINT16 handle);
+extern BOOLEAN bta_pan_hdl_event(BT_HDR *p_msg);
+
+/* action functions */
+extern void bta_pan_enable(tBTA_PAN_DATA *p_data);
+extern void bta_pan_disable(void);
+extern void bta_pan_set_role(tBTA_PAN_DATA *p_data);
+extern void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_api_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_set_shutdown(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_writebuf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+
+
+#endif /* BTA_PAN_INT_H */
diff --git a/bta/pan/bta_pan_main.c b/bta/pan/bta_pan_main.c
new file mode 100644
index 0000000..34caf61
--- /dev/null
+++ b/bta/pan/bta_pan_main.c
@@ -0,0 +1,409 @@
+/*****************************************************************************
+**
+** Name: bta_pan_main.c
+**
+** Description: This file contains the PAN main functions and
+** state machine.
+**
+** Copyright (c) 2004, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "gki.h"
+#include "pan_api.h"
+#include "bta_pan_api.h"
+#include "bta_pan_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_PAN_API_CLOSE,
+ BTA_PAN_TX_PATH,
+ BTA_PAN_RX_PATH,
+ BTA_PAN_TX_FLOW,
+ BTA_PAN_WRITE_BUF,
+ BTA_PAN_CONN_OPEN,
+ BTA_PAN_CONN_CLOSE,
+ BTA_PAN_FREE_BUF,
+ BTA_PAN_IGNORE
+};
+
+
+
+/* type for action functions */
+typedef void (*tBTA_PAN_ACTION)(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+
+
+
+
+/* action function list */
+const tBTA_PAN_ACTION bta_pan_action[] =
+{
+ bta_pan_api_close,
+ bta_pan_tx_path,
+ bta_pan_rx_path,
+ bta_pan_tx_flow,
+ bta_pan_write_buf,
+ bta_pan_conn_open,
+ bta_pan_conn_close,
+ bta_pan_free_buf,
+
+};
+
+/* state table information */
+#define BTA_PAN_ACTIONS 1 /* number of actions */
+#define BTA_PAN_NEXT_STATE 1 /* position of next state */
+#define BTA_PAN_NUM_COLS 2 /* number of columns in state tables */
+
+
+/* state machine states */
+enum
+{
+ BTA_PAN_IDLE_ST,
+ BTA_PAN_OPEN_ST,
+ BTA_PAN_CLOSING_ST
+};
+
+
+/* state table for listen state */
+const UINT8 bta_pan_st_idle[][BTA_PAN_NUM_COLS] =
+{
+ /* API_CLOSE */ {BTA_PAN_API_CLOSE, BTA_PAN_IDLE_ST},
+ /* CI_TX_READY */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
+ /* CI_RX_READY */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
+ /* CI_TX_FLOW */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
+ /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
+ /* CI_RX_WRITEBUF */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
+ /* PAN_CONN_OPEN */ {BTA_PAN_CONN_OPEN, BTA_PAN_OPEN_ST},
+ /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_OPEN, BTA_PAN_IDLE_ST},
+ /* FLOW_ENABLE */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST},
+ /* BNEP_DATA */ {BTA_PAN_IGNORE, BTA_PAN_IDLE_ST}
+
+};
+
+
+
+/* state table for open state */
+const UINT8 bta_pan_st_open[][BTA_PAN_NUM_COLS] =
+{
+ /* API_CLOSE */ {BTA_PAN_API_CLOSE, BTA_PAN_OPEN_ST},
+ /* CI_TX_READY */ {BTA_PAN_TX_PATH, BTA_PAN_OPEN_ST},
+ /* CI_RX_READY */ {BTA_PAN_RX_PATH, BTA_PAN_OPEN_ST},
+ /* CI_TX_FLOW */ {BTA_PAN_TX_FLOW, BTA_PAN_OPEN_ST},
+ /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_OPEN_ST},
+ /* CI_RX_WRITEBUF */ {BTA_PAN_WRITE_BUF, BTA_PAN_OPEN_ST},
+ /* PAN_CONN_OPEN */ {BTA_PAN_IGNORE, BTA_PAN_OPEN_ST},
+ /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_CLOSE, BTA_PAN_IDLE_ST},
+ /* FLOW_ENABLE */ {BTA_PAN_RX_PATH, BTA_PAN_OPEN_ST},
+ /* BNEP_DATA */ {BTA_PAN_TX_PATH, BTA_PAN_OPEN_ST}
+};
+
+/* state table for closing state */
+const UINT8 bta_pan_st_closing[][BTA_PAN_NUM_COLS] =
+{
+ /* API_CLOSE */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST},
+ /* CI_TX_READY */ {BTA_PAN_TX_PATH, BTA_PAN_CLOSING_ST},
+ /* CI_RX_READY */ {BTA_PAN_RX_PATH, BTA_PAN_CLOSING_ST},
+ /* CI_TX_FLOW */ {BTA_PAN_TX_FLOW, BTA_PAN_CLOSING_ST},
+ /* CI_RX_WRITE */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST},
+ /* CI_RX_WRITEBUF */ {BTA_PAN_FREE_BUF, BTA_PAN_CLOSING_ST},
+ /* PAN_CONN_OPEN */ {BTA_PAN_IGNORE, BTA_PAN_CLOSING_ST},
+ /* PAN_CONN_CLOSE */ {BTA_PAN_CONN_CLOSE, BTA_PAN_IDLE_ST},
+ /* FLOW_ENABLE */ {BTA_PAN_RX_PATH, BTA_PAN_CLOSING_ST},
+ /* BNEP_DATA */ {BTA_PAN_TX_PATH, BTA_PAN_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_PAN_ST_TBL)[BTA_PAN_NUM_COLS];
+
+/* state table */
+const tBTA_PAN_ST_TBL bta_pan_st_tbl[] = {
+ bta_pan_st_idle,
+ bta_pan_st_open,
+ bta_pan_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* PAN control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_PAN_CB bta_pan_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function bta_pan_scb_alloc
+**
+** Description Allocate a PAN server control block.
+**
+**
+** Returns pointer to the scb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+tBTA_PAN_SCB *bta_pan_scb_alloc(void)
+{
+ tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0];
+ int i;
+
+ for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++)
+ {
+ if (!p_scb->in_use)
+ {
+ p_scb->in_use = TRUE;
+ APPL_TRACE_DEBUG1("bta_pan_scb_alloc %d", i);
+ break;
+ }
+ }
+
+ if (i == BTA_PAN_NUM_CONN)
+ {
+ /* out of scbs */
+ p_scb = NULL;
+ APPL_TRACE_WARNING0("Out of scbs");
+ }
+ return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_sm_execute
+**
+** Description State machine event handling function for PAN
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_sm_execute(tBTA_PAN_SCB *p_scb, UINT16 event, tBTA_PAN_DATA *p_data)
+{
+ tBTA_PAN_ST_TBL state_table;
+ UINT8 action;
+ int i;
+
+ APPL_TRACE_EVENT3("PAN scb=%d event=0x%x state=%d", bta_pan_scb_to_idx(p_scb), event, p_scb->state);
+
+ /* look up the state table for the current state */
+ state_table = bta_pan_st_tbl[p_scb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_scb->state = state_table[event][BTA_PAN_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_PAN_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_PAN_IGNORE)
+ {
+ (*bta_pan_action[action])(p_scb, p_data);
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_api_enable
+**
+** Description Handle an API enable event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_api_enable(tBTA_PAN_DATA *p_data)
+{
+ /* initialize control block */
+ memset(&bta_pan_cb, 0, sizeof(bta_pan_cb));
+
+ /* store callback function */
+ bta_pan_cb.p_cback = p_data->api_enable.p_cback;
+ bta_pan_enable(p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_api_disable
+**
+** Description Handle an API disable event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_api_disable(tBTA_PAN_DATA *p_data)
+{
+ bta_pan_disable();
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_api_open
+**
+** Description Handle an API listen event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pan_api_open(tBTA_PAN_DATA *p_data)
+{
+ tBTA_PAN_SCB *p_scb;
+ tBTA_PAN_OPEN data;
+
+ /* allocate an scb */
+ if ((p_scb = bta_pan_scb_alloc()) != NULL)
+ {
+ bta_pan_open(p_scb, p_data);
+ }
+ else
+ {
+ bdcpy(data.bd_addr, p_data->api_open.bd_addr);
+ data.status = BTA_PAN_FAIL;
+ bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
+
+ }
+}
+/*******************************************************************************
+**
+** Function bta_pan_scb_dealloc
+**
+** Description Deallocate a link control block.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_scb_dealloc(tBTA_PAN_SCB *p_scb)
+{
+ APPL_TRACE_DEBUG1("bta_pan_scb_dealloc %d", bta_pan_scb_to_idx(p_scb));
+ memset(p_scb, 0, sizeof(tBTA_PAN_SCB));
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_scb_to_idx
+**
+** Description Given a pointer to an scb, return its index.
+**
+**
+** Returns Index of scb.
+**
+*******************************************************************************/
+UINT8 bta_pan_scb_to_idx(tBTA_PAN_SCB *p_scb)
+{
+
+ return ((UINT8) (p_scb - bta_pan_cb.scb)) + 1;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_pan_scb_by_handle
+**
+** Description Find scb associated with handle.
+**
+**
+** Returns Pointer to scb or NULL if not found.
+**
+*******************************************************************************/
+tBTA_PAN_SCB *bta_pan_scb_by_handle(UINT16 handle)
+{
+ tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0];
+ UINT8 i;
+
+ for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++)
+ {
+ if (p_scb->handle == handle)
+ {
+ return p_scb;;
+ }
+ }
+
+
+ APPL_TRACE_WARNING1("No scb for handle %d", handle);
+
+ return NULL;
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_hdl_event
+**
+** Description Data gateway main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_pan_hdl_event(BT_HDR *p_msg)
+{
+ tBTA_PAN_SCB *p_scb;
+ BOOLEAN freebuf = TRUE;
+
+ switch (p_msg->event)
+ {
+ /* handle enable event */
+ case BTA_PAN_API_ENABLE_EVT:
+ bta_pan_api_enable((tBTA_PAN_DATA *) p_msg);
+ break;
+
+ /* handle disable event */
+ case BTA_PAN_API_DISABLE_EVT:
+ bta_pan_api_disable((tBTA_PAN_DATA *) p_msg);
+ break;
+
+ /* handle set role event */
+ case BTA_PAN_API_SET_ROLE_EVT:
+ bta_pan_set_role((tBTA_PAN_DATA *) p_msg);
+ break;
+
+ /* handle open event */
+ case BTA_PAN_API_OPEN_EVT:
+ bta_pan_api_open((tBTA_PAN_DATA *) p_msg);
+ break;
+
+
+ /* events that require buffer not be released */
+ case BTA_PAN_CI_RX_WRITEBUF_EVT:
+ freebuf = FALSE;
+ if ((p_scb = bta_pan_scb_by_handle(p_msg->layer_specific)) != NULL)
+ {
+ bta_pan_sm_execute(p_scb, p_msg->event, (tBTA_PAN_DATA *) p_msg);
+ }
+ break;
+
+ /* all other events */
+ default:
+ if ((p_scb = bta_pan_scb_by_handle(p_msg->layer_specific)) != NULL)
+ {
+ bta_pan_sm_execute(p_scb, p_msg->event, (tBTA_PAN_DATA *) p_msg);
+ }
+ break;
+
+ }
+ return freebuf;
+}
+#endif /* BTA_PAN_INCLUDED */
diff --git a/bta/pb/bta_pbs_act.c b/bta/pb/bta_pbs_act.c
new file mode 100644
index 0000000..98f6463
--- /dev/null
+++ b/bta/pb/bta_pbs_act.c
@@ -0,0 +1,1134 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_act.c
+**
+** Description: This file contains the phone book access server
+** functions for the state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_fs_api.h"
+#include "bta_pbs_api.h"
+#include "bta_pbs_int.h"
+#include "btm_api.h"
+#include "utl.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+#define FLAGS_ARE_MASK (OBX_SPF_BACKUP | OBX_SPF_NO_CREATE)
+#define FLAGS_ARE_ILLEGAL 0x1 /* 'Backup and Create flag combo is BAD */
+/*****************************************************************************
+** Local Function prototypes
+*****************************************************************************/
+#if BTA_PBS_DEBUG == TRUE
+static char *pbs_obx_evt_code(tOBX_EVENT evt_code);
+#endif
+
+/*****************************************************************************
+** Action Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_pbs_api_disable
+**
+** Description Stop PBS server.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_api_disable(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ /* Free any outstanding headers and control block memory */
+ bta_pbs_clean_getput(p_cb, TRUE);
+
+ /* Stop the OBEX server */
+ OBX_StopServer(p_cb->obx_handle);
+
+ /* Remove the PBS service from the SDP database */
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ bta_sys_remove_uuid(UUID_SERVCLASS_PBAP_PSE);
+ /* Free the allocated server channel number */
+ BTM_FreeSCN(p_cb->scn);
+ BTM_SecClrService(BTM_SEC_SERVICE_PBAP);
+
+ utl_freebuf((void**)&p_cb->p_rootpath); /* Free buffer containing root and working paths */
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_api_authrsp
+**
+** Description Pass the response to an authentication request back to the
+** client.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_api_authrsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ UINT8 *p_pwd = NULL;
+ UINT8 *p_userid = NULL;
+
+ if (p_data->auth_rsp.key_len > 0)
+ p_pwd = (UINT8 *)p_data->auth_rsp.key;
+ if (p_data->auth_rsp.userid_len > 0)
+ p_userid = (UINT8 *)p_data->auth_rsp.userid;
+
+ OBX_Password(p_cb->obx_handle, p_pwd, p_data->auth_rsp.key_len,
+ p_userid, p_data->auth_rsp.userid_len);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_api_close
+**
+** Description Handle an api close event.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_api_close(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ BD_ADDR bd_addr;
+ if (OBX_GetPeerAddr(p_cb->obx_handle, bd_addr) != 0)
+ {
+ /* resources will be freed at BTA_PBS_OBX_CLOSE_EVT */
+ OBX_DisconnectRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, NULL);
+ }
+ else
+ {
+ p_cb->p_cback(BTA_PBS_CLOSE_EVT, 0);
+}
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_api_accessrsp
+**
+** Description Process the access API event.
+** If permission had been granted, continue the operation,
+** otherwise stop the operation.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_api_accessrsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ UINT8 rsp_code = OBX_RSP_OK;
+ tBTA_PBS_CO_STATUS status = BTA_PBS_CO_EACCES;
+ tBTA_PBS_ACCESS_TYPE access = p_data->access_rsp.flag;
+ tBTA_PBS_OPER old_acc_active = p_cb->acc_active;
+ tBTA_PBS_OBX_RSP *p_rsp = NULL;
+ tBTA_PBS_OBJECT objevt;
+
+ if(p_cb->acc_active != p_data->access_rsp.oper )
+ {
+ APPL_TRACE_WARNING2("PBS ACCRSP: not match active:%d, rsp:%d",
+ p_cb->acc_active, p_data->access_rsp.oper);
+ return;
+ }
+
+ p_cb->acc_active = 0;
+ /* Process the currently active access response */
+ switch (old_acc_active)
+ {
+ case BTA_PBS_OPER_PULL_PB:
+ case BTA_PBS_OPER_PULL_VCARD_ENTRY:
+ if (access == BTA_PBS_ACCESS_TYPE_ALLOW)
+ {
+ p_cb->cout_active = TRUE;
+ bta_pbs_co_open(p_cb->p_path, p_cb->obx_oper, &p_cb->pullpb_app_params);
+ }
+
+ /* Case where application determined requested vCard handle has been modified: Requests a new listing to clear */
+ else if (access == BTA_PBS_ACCESS_TYPE_PRECONDITION && old_acc_active == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ bta_pbs_get_file_rsp(OBX_RSP_PRECONDTN_FAILED, 0);
+ else /* Denied */
+ bta_pbs_get_file_rsp(OBX_RSP_UNAUTHORIZED, 0);
+ break;
+ case BTA_PBS_OPER_PULL_VCARD_LIST:
+ if (access == BTA_PBS_ACCESS_TYPE_ALLOW)
+ {
+ /* continue with get vlist */
+ bta_pbs_getvlist(p_cb->p_name);
+ }
+ else
+ bta_pbs_get_file_rsp(OBX_RSP_UNAUTHORIZED, 0);
+ break;
+
+ case BTA_PBS_OPER_SET_PB: /* Request is a Change Folder */
+ p_rsp = OBX_SetPathRsp;
+ if (access == BTA_PBS_ACCESS_TYPE_ALLOW)
+ {
+ status = BTA_PBS_CO_OK;
+ /* set obj type based on path */
+ if (!memcmp(p_cb->p_name, BTA_PBS_PBFOLDER_NAME, sizeof(BTA_PBS_PBFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_PB_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_ICHFOLDER_NAME, sizeof(BTA_PBS_ICHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_ICH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_OCHFOLDER_NAME, sizeof(BTA_PBS_OCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_OCH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_MCHFOLDER_NAME, sizeof(BTA_PBS_MCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_MCH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_CCHFOLDER_NAME, sizeof(BTA_PBS_CCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_CCH_OBJ;
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+ APPL_TRACE_DEBUG1("PBS: SET NEW PATH [%s]", p_cb->p_workdir);
+ }
+ break;
+
+ default:
+ p_cb->acc_active = old_acc_active;
+ APPL_TRACE_WARNING1("PBS ACCRSP: Unknown tBTA_PBS_OPER value (%d)",
+ p_cb->acc_active);
+ break;
+ }
+
+ /* Set Path Done */
+ if(p_rsp && old_acc_active == BTA_PBS_OPER_SET_PB)
+ {
+ switch (status)
+ {
+ case BTA_PBS_CO_OK:
+ rsp_code = OBX_RSP_OK;
+ break;
+ case BTA_PBS_CO_EACCES:
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ break;
+ default:
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+ break;
+ }
+ if (p_cb->p_cback)
+ {
+ objevt.operation = p_cb->obx_oper;
+ objevt.p_name = p_cb->p_path;
+ objevt.status = (status == BTA_PBS_CO_OK ? BTA_PBS_OK: BTA_PBS_FAIL);
+ (p_cb->p_cback) (BTA_PBS_OPER_CMPL_EVT, (tBTA_PBS *) &objevt);
+ }
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+ p_cb->obx_oper = BTA_PBS_OPER_NONE;
+ (*p_rsp)(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_vlist_act
+**
+** Description Continue getting the current vlist entry operation
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_vlist_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ UINT8 rsp_code;
+ tBTA_PBS_CI_VLIST_EVT *p_revt = &p_data->vlist_evt;
+
+ p_cb->cout_active = FALSE;
+
+ /* Process vcard listing call-in event if operation is still active */
+ if (p_cb->obx_oper == BTA_PBS_OPER_PULL_VCARD_LIST)
+ {
+ switch (p_revt->status)
+ {
+ case BTA_PBS_CO_OK:
+ p_cb->num_vlist_idxs++;
+
+ /* Valid new entry */
+ if (!strcmp(p_cb->vlist.handle, ".") || !strcmp(p_cb->vlist.handle, "..")
+ || p_cb->vlist.handle[0] == '\0') {
+ /* don't count this entry */
+ p_cb->num_vlist_idxs--;
+
+ /* continue get */
+ if (p_revt->final) {
+ /* if it is final */
+ bta_pbs_end_of_list(OBX_RSP_OK);
+ } else {
+ p_cb->cout_active = TRUE;
+ bta_pbs_co_getvlist(p_cb->p_path, &p_cb->getvlist_app_params,
+ FALSE, &p_cb->vlist);
+ }
+ } else if ((rsp_code = bta_pbs_add_list_entry()) == OBX_RSP_OK) {
+ /* if we can add the entry */
+ if (p_revt->final) {
+ /* if it is final */
+ bta_pbs_end_of_list(rsp_code);
+ } else {
+ /* continue get */
+ p_cb->cout_active = TRUE;
+ bta_pbs_co_getvlist(p_cb->p_path, &p_cb->getvlist_app_params,
+ FALSE, &p_cb->vlist);
+ }
+ } else if (rsp_code == OBX_RSP_CONTINUE) {
+ /* do not have enough data buffer, send obex continue to client */
+ if (p_revt->final) {
+ /* if this is the last VCard list entry */
+ p_cb->obx.final_pkt = TRUE;
+ }
+ bta_pbs_end_of_list(rsp_code);
+ } else {
+ bta_pbs_end_of_list(rsp_code);
+ }
+ break;
+
+ case BTA_PBS_CO_FAIL: /* Error occurred */
+ bta_pbs_end_of_list(OBX_RSP_SERVICE_UNAVL);
+ break;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_read
+**
+** Description Handles the response to a read call-out request.
+** This is called within the OBX get file request. If the
+** operation has completed, the OBX response is sent out;
+** otherwise a read for additional data is made.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_read_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_CI_READ_EVT *p_revt = &p_data->read_evt;
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+ p_cb->cout_active = FALSE;
+ if (p_cb->aborting)
+ {
+ bta_pbs_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ return;
+ }
+
+ /* Process read call-in event if operation is still active */
+ if ((p_cb->obx_oper == BTA_PBS_OPER_PULL_PB || p_cb->obx_oper == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ && p_revt->fd == p_cb->fd)
+ {
+ /* Read was successful, not finished yet */
+ if (p_revt->status == BTA_PBS_CO_OK && !p_revt->final)
+ rsp_code = OBX_RSP_CONTINUE;
+ if (p_revt->status == BTA_PBS_CO_OK && p_revt->final)
+ rsp_code = OBX_RSP_OK;
+
+ /* Process response to OBX client */
+ bta_pbs_get_file_rsp(rsp_code, p_revt->num_read);
+ }
+ else
+ {
+ bta_pbs_get_file_rsp(rsp_code, 0);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_open
+**
+** Description Continue with the current file open operation
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_open_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_CI_OPEN_EVT *p_open = &p_data->open_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 pb_size = 0, new_missed_call = 0, len=0;
+ UINT8 *p, *p_start;
+
+ p_cb->cout_active = FALSE;
+
+ if (p_cb->aborting)
+ {
+ bta_pbs_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, OBX_RSP_OK, (BT_HDR *)NULL);
+ return;
+ }
+
+ /* Only process file get operations */
+ if (p_cb->obx_oper == BTA_PBS_OPER_PULL_PB || p_cb->obx_oper == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ {
+ if (p_open->status == BTA_PBS_CO_OK)
+ {
+ p_cb->file_length = p_open->file_size;
+ p_cb->fd = p_open->fd;
+
+ /* add other application header */
+ if (p_cb->obx_oper == BTA_PBS_OPER_PULL_PB)
+ {
+ if (p_cb->pullpb_app_params.max_count == 0 ||
+ p_cb->obj_type == BTA_PBS_MCH_OBJ)
+ {
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ bta_pbs_co_getpbinfo(p_cb->obx_oper, p_cb->obj_type, &pb_size, &new_missed_call);
+ p = p_start;
+ if (p_cb->pullpb_app_params.max_count == 0)
+ {
+ *p++ = BTA_PBS_TAG_PB_SIZE;
+ *p++ = 2;
+ UINT16_TO_BE_STREAM(p, pb_size);
+ /* if max count = 0, client want to know the pb size */
+ p_cb->file_length = 0;
+ }
+ if (p_cb->obj_type == BTA_PBS_MCH_OBJ)
+ {
+ *p++ = BTA_PBS_TAG_NEW_MISSED_CALLS;
+ *p++ = 1;
+ *p++ = (UINT8) new_missed_call;
+ }
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+ }
+
+ if (p_cb->file_length > 0)
+ {
+ /* contiune to get file */
+ bta_pbs_proc_get_file(p_cb->p_name, p_cb->obx_oper);
+ }
+ else
+ {
+ /* If file length is zero, add end body header */
+ if (((p_cb->obx_oper == BTA_PBS_OPER_PULL_PB) && p_cb->pullpb_app_params.max_count) || p_cb->obx_oper == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ {
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, 0, TRUE);
+ }
+ bta_pbs_get_file_rsp(rsp_code, 0);
+ }
+ }
+ else
+ {
+ if (p_open->status == BTA_PBS_CO_EACCES)
+ rsp_code = OBX_RSP_UNAUTHORIZED;
+ else /* File could not be found */
+ rsp_code = OBX_RSP_NOT_FOUND;
+
+ /* Send OBX response if an error occurred */
+ bta_pbs_get_file_rsp(rsp_code, 0);
+ }
+ }
+
+ return;
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_connect
+**
+** Description Process the OBX connect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_connect(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ tBTA_PBS_OPEN open_evt;
+ char *p_devname;
+
+ p_cb->peer_mtu = p_evt->param.conn.mtu;
+ memcpy(p_cb->bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN);
+ APPL_TRACE_EVENT1("PBS Connect: peer mtu 0x%04x", p_cb->peer_mtu);
+
+ OBX_ConnectRsp(p_evt->handle, OBX_RSP_OK, (BT_HDR *)NULL);
+
+ /* Reset to the root directory */
+ BCM_STRNCPY_S(p_cb->p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+
+ /* inform role manager */
+ bta_sys_conn_open(BTA_ID_PBS ,p_cb->app_id, p_cb->bd_addr);
+
+ /* Notify the MMI that a connection has been opened */
+ memcpy(open_evt.bd_addr, p_evt->param.conn.peer_addr, BD_ADDR_LEN);
+ if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL)
+ BCM_STRNCPY_S((char *)open_evt.dev_name, sizeof(tBTM_BD_NAME), p_devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ p_cb->p_cback(BTA_PBS_OPEN_EVT, (tBTA_PBS *) &open_evt);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_disc
+**
+** Description Process the OBX disconnect event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_disc(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code;
+
+ rsp_code = (p_evt->obx_event == OBX_DISCONNECT_REQ_EVT) ? OBX_RSP_OK
+ : OBX_RSP_BAD_REQUEST;
+ OBX_DisconnectRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_close
+**
+** Description Process the OBX link lost event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_close(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ /* finished if not waiting on a call-in function */
+ if (!p_cb->cout_active)
+ bta_pbs_sm_execute(p_cb, BTA_PBS_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_abort
+**
+** Description Process the OBX abort event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_abort(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_OK;
+
+ utl_freebuf((void**)&p_evt->p_pkt);
+
+ if (!p_cb->cout_active)
+ {
+ bta_pbs_clean_getput(p_cb, TRUE);
+ OBX_AbortRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ }
+ else /* Delay the response if a call-out function is active */
+ p_cb->aborting = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_password
+**
+** Description Process the OBX password request
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_password(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ tBTA_PBS_AUTH *p_auth;
+ BOOLEAN is_challenged;
+ tOBX_AUTH_OPT options;
+
+ if ((p_auth = (tBTA_PBS_AUTH *)GKI_getbuf(sizeof(tBTA_PBS_AUTH))) != NULL)
+ {
+ memset(p_auth, 0, sizeof(tBTA_PBS_AUTH));
+
+ /* Extract user id from packet (if available) */
+ if (OBX_ReadAuthParams(p_data->obx_evt.p_pkt, &p_auth->p_userid,
+ &p_auth->userid_len,
+ &is_challenged, &options))
+ {
+ if (options & OBX_AO_USR_ID)
+ p_auth->userid_required = TRUE;
+ }
+
+
+ /* Notify application */
+ p_cb->p_cback(BTA_PBS_AUTH_EVT, (tBTA_PBS *)p_auth);
+
+ GKI_freebuf(p_auth);
+ }
+ /* Don't need OBX packet any longer */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_get
+**
+** Description Process the OBX file get and folder listing events
+** If the type header is not folder listing, then pulling a file.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_get(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT16 len;
+ UINT8 *p_type;
+ UINT8 *p_param;
+ UINT16 param_len;
+ tBTA_PBS_OPER operation = 0;
+
+ /* If currently processing a GET, use the current name */
+ if (bta_pbs_cb.obx_oper == BTA_PBS_OPER_PULL_VCARD_LIST)
+ bta_pbs_getvlist(p_cb->p_name);
+ else if (bta_pbs_cb.obx_oper == BTA_PBS_OPER_PULL_PB ||
+ bta_pbs_cb.obx_oper == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ bta_pbs_proc_get_file(p_cb->p_name, bta_pbs_cb.obx_oper);
+ else /* This is a new request */
+ {
+ /* Pull out the name header if it exists */
+ if ((p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1))) != NULL)
+ {
+ if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+
+ GKI_freebuf(p_cb->p_name);
+ p_cb->p_name = NULL;
+
+#if 0 /* Peer spec violation, but some platforms do this wrong, so relaxing requirement.
+ enable this if strict error checking needed */
+ utl_freebuf((void**)&p_evt->p_pkt);
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ return;
+#endif
+ }
+ } else {
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_SERVICE_UNAVL, (BT_HDR *)NULL);
+ utl_freebuf((void**)&p_evt->p_pkt);
+ return;
+ }
+
+ /* See what type of operations */
+ if (OBX_ReadTypeHdr(p_evt->p_pkt, &p_type, &len))
+ {
+ if (!memcmp(p_type, BTA_PBS_GETVCARD_LISTING_TYPE, len))
+ {
+
+ if ((p_cb->p_name) && strlen(p_cb->p_name))
+ {
+ APPL_TRACE_EVENT1("PBS VList Get: Name [%s]", p_cb->p_name);
+ }
+ else /* This is a peer spec violation, but allowing for better IOP */
+ {
+ APPL_TRACE_WARNING0("PBS OBX GET: Missing Name Header...Assuming current directory");
+
+ /* Errata 1824: It is illegal to issue a PullvCardListing request with an empty
+ name header from the "telecom" folder */
+ if (p_cb->p_workdir && !strcmp(&(p_cb->p_workdir[strlen(p_cb->p_workdir) - 7]), "telecom"))
+ {
+ utl_freebuf((void**)&p_evt->p_pkt);
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_NOT_FOUND, (BT_HDR *)NULL);
+ return;
+ }
+ }
+
+ /* read application params */
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_MAX_LIST_COUNT, &param_len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->getvlist_app_params.max_count, p_param);
+ }
+ else
+ {
+ p_cb->getvlist_app_params.max_count = BTA_PBS_MAX_LIST_COUNT;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_LIST_START_OFFSET, &param_len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->getvlist_app_params.start_offset, p_param);
+ }
+ else
+ {
+ p_cb->getvlist_app_params.start_offset = 0;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_ORDER, &param_len);
+ if (p_param)
+ {
+ p_cb->getvlist_app_params.order = *p_param;
+ }
+ else
+ {
+ p_cb->getvlist_app_params.order = BTA_PBS_ORDER_INDEX;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_SEARCH_ATTRIBUTE, &param_len);
+ if (p_param)
+ {
+ p_cb->getvlist_app_params.attribute = *p_param;
+ }
+ else
+ {
+ p_cb->getvlist_app_params.attribute = 0;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_SEARCH_VALUE, &param_len);
+ if (p_param)
+ {
+ memcpy(p_cb->getvlist_app_params.p_value, p_param, param_len);
+ p_cb->getvlist_app_params.value_len = param_len;
+ }
+ else
+ {
+ p_cb->getvlist_app_params.value_len = 0;
+ }
+
+ /* Assume downloading vCard Listing if no name */
+ p_cb->obj_type = BTA_PBS_PB_OBJ;
+
+ if (p_cb->p_name)
+ {
+/* if (!memcmp(p_cb->p_name, BTA_PBS_PBFOLDER_NAME, sizeof(BTA_PBS_PBFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_PB_OBJ; <-- default type */
+ if (!memcmp(p_cb->p_name, BTA_PBS_ICHFOLDER_NAME, sizeof(BTA_PBS_ICHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_ICH_OBJ;
+ else if (!memcmp(p_cb->p_name, BTA_PBS_OCHFOLDER_NAME, sizeof(BTA_PBS_OCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_OCH_OBJ;
+ else if (!memcmp(p_cb->p_name, BTA_PBS_MCHFOLDER_NAME, sizeof(BTA_PBS_MCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_MCH_OBJ;
+ else if (!memcmp(p_cb->p_name, BTA_PBS_CCHFOLDER_NAME, sizeof(BTA_PBS_CCHFOLDER_NAME)))
+ p_cb->obj_type = BTA_PBS_CCH_OBJ;
+ }
+ bta_pbs_getvlist(p_cb->p_name);
+ }
+ else if (!memcmp(p_type, BTA_PBS_GETFILE_TYPE, len) ||
+ !memcmp(p_type, BTA_PBS_GETVARD_ENTRY_TYPE, len))
+ {
+ if (!memcmp(p_type, BTA_PBS_GETFILE_TYPE, len))
+ operation = BTA_PBS_OPER_PULL_PB;
+ else
+ operation = BTA_PBS_OPER_PULL_VCARD_ENTRY;
+ /* read application params */
+ if (p_cb->p_name)
+ {
+ APPL_TRACE_EVENT2("PBS File Get: Name [%s], operation %d", p_cb->p_name, operation);
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_FILTER, &param_len);
+ if (p_param)
+ {
+ if (param_len == 8)
+ p_param += 4; /* skip the first 4 bytes, we do not handle proprietary AttributesMask */
+ BE_STREAM_TO_UINT32(p_cb->pullpb_app_params.filter, p_param);
+ }
+ else
+ {
+ p_cb->pullpb_app_params.filter = BTA_PBS_FILTER_ALL;
+ }
+
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_FORMAT, &param_len);
+ if (p_param)
+ {
+ p_cb->pullpb_app_params.format = *p_param;
+ }
+ else
+ {
+ p_cb->pullpb_app_params.format = BTA_PBS_VCF_FMT_21;
+ }
+
+ /* set the object type for pull pb */
+ if (operation == BTA_PBS_OPER_PULL_PB)
+ {
+ if (p_cb->p_name == NULL)
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ else
+ {
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLPB_NAME, sizeof(BTA_PBS_PULLPB_NAME)))
+ p_cb->obj_type = BTA_PBS_PB_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLICH_NAME, sizeof(BTA_PBS_PULLICH_NAME)))
+ p_cb->obj_type = BTA_PBS_ICH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLOCH_NAME, sizeof(BTA_PBS_PULLOCH_NAME)))
+ p_cb->obj_type = BTA_PBS_OCH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLMCH_NAME, sizeof(BTA_PBS_PULLMCH_NAME)))
+ p_cb->obj_type = BTA_PBS_MCH_OBJ;
+ if (!memcmp(p_cb->p_name, BTA_PBS_PULLCCH_NAME, sizeof(BTA_PBS_PULLCCH_NAME)))
+ p_cb->obj_type = BTA_PBS_CCH_OBJ;
+ }
+ }
+ /* for pull pb, read app params for max list count and start offset */
+ if (operation == BTA_PBS_OPER_PULL_PB)
+ {
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_MAX_LIST_COUNT, &param_len);
+ if (p_param)
+ BE_STREAM_TO_UINT16(p_cb->pullpb_app_params.max_count, p_param);
+ p_param = bta_pbs_read_app_params(p_evt->p_pkt, BTA_PBS_TAG_LIST_START_OFFSET, &param_len);
+ if (p_param)
+ {
+ BE_STREAM_TO_UINT16(p_cb->pullpb_app_params.start_offset, p_param);
+ }
+ else
+ {
+ p_cb->pullpb_app_params.start_offset = 0;
+ }
+ }
+ bta_pbs_proc_get_file(p_cb->p_name, operation);
+ }
+ else {
+ OBX_GetRsp(p_cb->obx_handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ }
+ }
+ }
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_obx_setpath
+**
+** Description Process the PBS change directory requests
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_setpath(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+ UINT8 rsp_code = OBX_RSP_BAD_REQUEST;
+ tOBX_SETPATH_FLAG *p_flag = &p_evt->param.sp.flag;
+ tBTA_PBS_OPER pbs_op = 0;
+ tBTA_PBS_OBJECT objevt;
+
+ /* Verify flags and handle before accepting */
+ if (p_evt->handle == p_cb->obx_handle &&
+ (((*p_flag) & FLAGS_ARE_MASK) != FLAGS_ARE_ILLEGAL))
+ {
+ p_cb->obx_oper = BTA_PBS_OPER_SET_PB;
+ p_cb->p_name = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_file_len + 1));
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len +
+ p_bta_fs_cfg->max_file_len + 2));
+ if (p_cb->p_name != NULL && p_cb->p_path != NULL)
+ {
+ if (!OBX_ReadUtf8NameHdr(p_evt->p_pkt, (UINT8 *)p_cb->p_name, p_bta_fs_cfg->max_file_len))
+ {
+ p_cb->p_name[0] = 0;
+ }
+
+ rsp_code = bta_pbs_chdir(p_evt->p_pkt, (BOOLEAN)((*p_flag) & OBX_SPF_BACKUP), &pbs_op);
+ }
+ else
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+ }
+
+ if(pbs_op)
+ {
+ bta_pbs_req_app_access(pbs_op, p_cb);
+ }
+ else
+ {
+ if (p_cb->p_cback)
+ {
+ objevt.operation = BTA_PBS_OPER_SET_PB;
+ objevt.p_name = p_cb->p_path;
+ objevt.status = (rsp_code == OBX_RSP_OK ? BTA_PBS_OK: BTA_PBS_FAIL);
+ (p_cb->p_cback) (BTA_PBS_OPER_CMPL_EVT, (tBTA_PBS *) &objevt);
+ }
+ p_cb->obx_oper = BTA_PBS_OPER_NONE;
+ OBX_SetPathRsp(p_evt->handle, rsp_code, (BT_HDR *)NULL);
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+ }
+
+ /* Done with Obex packet */
+ utl_freebuf((void**)&p_evt->p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_appl_tout
+**
+** Description Process the PBS application timeout event
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_appl_tout(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_conn_err_rsp
+**
+** Description Process the OBX error response
+** Connect request received in wrong state, or bad request
+** from client
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_conn_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ OBX_ConnectRsp(p_data->obx_evt.handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_disc_err_rsp
+**
+** Description Process the OBX error response
+** Disconnect request received in wrong state, or bad request
+** from client
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_disc_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ OBX_DisconnectRsp(p_data->obx_evt.handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_gasp_err_rsp
+**
+** Description Process the OBX error response for Get, Abort, Setpath.
+**
+** The rsp_code field of tBTA_PBS_DATA (obx_evt) contains the
+** response code to be sent to OBEX, and the obx_event field
+** contains the current OBEX event.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_gasp_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_OBX_EVENT *p_evt = &p_data->obx_evt;
+
+ switch (p_evt->obx_event)
+ {
+ case OBX_GET_REQ_EVT:
+ OBX_GetRsp(p_evt->handle, p_evt->rsp_code, (BT_HDR *)NULL);
+ break;
+ case OBX_SETPATH_REQ_EVT:
+ OBX_SetPathRsp(p_evt->handle, p_evt->rsp_code, (BT_HDR *)NULL);
+ break;
+ case OBX_ABORT_REQ_EVT:
+ OBX_AbortRsp(p_evt->handle, p_evt->rsp_code, (BT_HDR *)NULL);
+ break;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_close_complete
+**
+** Description Finishes the memory cleanup after a channel is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_close_complete(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ p_cb->cout_active = FALSE;
+ bta_pbs_clean_getput(p_cb, TRUE);
+
+ /* inform role manager */
+ bta_sys_conn_close( BTA_ID_PBS ,p_cb->app_id, p_cb->bd_addr);
+
+ memset(p_cb->bd_addr, 0, BD_ADDR_LEN);
+
+ /* Notify the MMI that a connection has been closed */
+ p_cb->p_cback(BTA_PBS_CLOSE_EVT, 0);
+
+ if (p_data->obx_evt.p_pkt)
+ APPL_TRACE_WARNING0("PBS: OBX CLOSE CALLED WITH non-NULL Packet!!!");
+}
+
+/*****************************************************************************
+** Callback Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_pbs_obx_cback
+**
+** Description OBX callback function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_obx_cback (tOBX_HANDLE handle, tOBX_EVENT obx_event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt)
+{
+ tBTA_PBS_OBX_EVENT *p_obx_msg;
+ UINT16 event = 0;
+
+#if BTA_PBS_DEBUG == TRUE
+ APPL_TRACE_DEBUG1("OBX Event Callback: obx_event [%s]", pbs_obx_evt_code(obx_event));
+#endif
+
+ switch(obx_event)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ event = BTA_PBS_OBX_CONN_EVT;
+ break;
+ case OBX_DISCONNECT_REQ_EVT:
+ event = BTA_PBS_OBX_DISC_EVT;
+ break;
+ case OBX_GET_REQ_EVT:
+ event = BTA_PBS_OBX_GET_EVT;
+ break;
+ case OBX_SETPATH_REQ_EVT:
+ event = BTA_PBS_OBX_SETPATH_EVT;
+ break;
+ case OBX_ABORT_REQ_EVT:
+ event = BTA_PBS_OBX_ABORT_EVT;
+ break;
+ case OBX_CLOSE_IND_EVT:
+ event = BTA_PBS_OBX_CLOSE_EVT;
+ break;
+ case OBX_TIMEOUT_EVT:
+ break;
+ case OBX_PASSWORD_EVT:
+ event = BTA_PBS_OBX_PASSWORD_EVT;
+ break;
+ /* send Bad Request for Obex put request */
+ case OBX_PUT_REQ_EVT:
+ OBX_PutRsp(handle, OBX_RSP_BAD_REQUEST, (BT_HDR *)NULL);
+ if (p_pkt)
+ utl_freebuf((void**)&p_pkt);
+ return;
+ break;
+ default:
+ /* Unrecognized packet; disconnect the session */
+ if (p_pkt)
+ {
+ event = BTA_PBS_OBX_DISC_EVT;
+ utl_freebuf((void**)&p_pkt);
+ }
+ break;
+ }
+
+ /* send event to BTA, if any */
+ if (event && (p_obx_msg =
+ (tBTA_PBS_OBX_EVENT *) GKI_getbuf(sizeof(tBTA_PBS_OBX_EVENT))) != NULL)
+ {
+ p_obx_msg->hdr.event = event;
+ p_obx_msg->obx_event = obx_event;
+ p_obx_msg->handle = handle;
+ p_obx_msg->param = param;
+ p_obx_msg->p_pkt = p_pkt;
+
+ bta_sys_sendmsg(p_obx_msg);
+ }
+}
+
+/*****************************************************************************
+** Local PBS Event Processing Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function bta_pbs_req_app_access
+**
+** Description Sends an access request event to the application.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_req_app_access (tBTA_PBS_OPER oper, tBTA_PBS_CB *p_cb)
+{
+ tBTA_PBS_ACCESS *p_acc_evt;
+ char *p_devname;
+
+ /* Notify the application that a get file has been requested */
+ if ((p_acc_evt = (tBTA_PBS_ACCESS *)GKI_getbuf(sizeof(tBTA_PBS_ACCESS))) != NULL)
+ {
+ memset(p_acc_evt, 0, sizeof(tBTA_PBS_ACCESS));
+
+ APPL_TRACE_API1("ACCESS REQ: [%s]", p_cb->p_path);
+ p_acc_evt->p_name = p_cb->p_path;
+ p_acc_evt->oper = p_cb->acc_active = oper;
+ bdcpy(p_acc_evt->bd_addr, p_cb->bd_addr);
+ if ((p_devname = BTM_SecReadDevName(p_cb->bd_addr)) != NULL)
+ BCM_STRNCPY_S((char *)p_acc_evt->dev_name, sizeof(tBTM_BD_NAME), p_devname, BTM_MAX_REM_BD_NAME_LEN);
+
+ p_cb->p_cback(BTA_PBS_ACCESS_EVT, (tBTA_PBS *)p_acc_evt);
+ GKI_freebuf(p_acc_evt);
+ }
+}
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_PBS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function pbs_obx_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *pbs_obx_evt_code(tOBX_EVENT evt_code)
+{
+ switch(evt_code)
+ {
+ case OBX_CONNECT_REQ_EVT:
+ return "OBX_CONNECT_REQ_EVT";
+ case OBX_DISCONNECT_REQ_EVT:
+ return "OBX_DISCONNECT_REQ_EVT";
+ case OBX_GET_REQ_EVT:
+ return "OBX_GET_REQ_EVT";
+ case OBX_SETPATH_REQ_EVT:
+ return "OBX_SETPATH_REQ_EVT";
+ case OBX_ABORT_REQ_EVT:
+ return "OBX_ABORT_REQ_EVT";
+ case OBX_CLOSE_IND_EVT:
+ return "OBX_CLOSE_IND_EVT";
+ case OBX_TIMEOUT_EVT:
+ return "OBX_TIMEOUT_EVT";
+ case OBX_PASSWORD_EVT:
+ return "OBX_PASSWORD_EVT";
+ default:
+ return "unknown OBX event code";
+ }
+}
+#endif /* Debug Functions */
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_api.c b/bta/pb/bta_pbs_api.c
new file mode 100644
index 0000000..c8466f6
--- /dev/null
+++ b/bta/pb/bta_pbs_api.c
@@ -0,0 +1,222 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_api.c
+**
+** Description: This is the implementation of the API for the phone book
+** access server subsystem of BTA, Widcomm's Bluetooth
+** application layer for mobile phones.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_fs_api.h"
+#include "bta_pbs_api.h"
+#include "bta_pbs_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_pbs_reg =
+{
+ bta_pbs_hdl_event,
+ BTA_PbsDisable
+};
+
+/*******************************************************************************
+**
+** Function BTA_PbsEnable
+**
+** Description Enable the phone book access server. This function must be
+** called before any other functions in the PB Server API are called.
+** When the enable operation is complete the callback function
+** will be called with an BTA_PBS_ENABLE_EVT event.
+** Note: Pbs always enable (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT)
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsEnable(tBTA_SEC sec_mask, const char *p_service_name,
+ const char *p_root_path, BOOLEAN enable_authen,
+ UINT8 realm_len, UINT8 *p_realm,
+ tBTA_PBS_CBACK *p_cback, UINT8 app_id)
+{
+ tBTA_PBS_API_ENABLE *p_buf;
+
+ /* register with BTA system manager */
+ GKI_sched_lock();
+ bta_sys_register(BTA_ID_PBS, &bta_pbs_reg);
+ GKI_sched_unlock();
+
+ if ((p_buf = (tBTA_PBS_API_ENABLE *)GKI_getbuf((UINT16)(sizeof(tBTA_PBS_API_ENABLE) +
+ p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ memset(p_buf, 0, sizeof(tBTA_PBS_API_ENABLE));
+
+ p_buf->p_root_path = (char *)(p_buf + 1);
+ p_buf->p_root_path[0] = '\0';
+
+ p_buf->hdr.event = BTA_PBS_API_ENABLE_EVT;
+ p_buf->p_cback = p_cback;
+ p_buf->sec_mask = (sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+ p_buf->app_id = app_id;
+ p_buf->auth_enabled = enable_authen;
+
+ p_buf->realm_len = (realm_len < OBX_MAX_REALM_LEN) ? realm_len :
+ OBX_MAX_REALM_LEN;
+ if (p_realm)
+ memcpy(p_buf->realm, p_realm, p_buf->realm_len);
+
+ if (p_service_name)
+ {
+ BCM_STRNCPY_S(p_buf->servicename, sizeof(p_buf->servicename), p_service_name, BTA_SERVICE_NAME_LEN);
+ p_buf->servicename[BTA_SERVICE_NAME_LEN] = '\0';
+ }
+
+ if (p_root_path)
+ {
+ BCM_STRNCPY_S(p_buf->p_root_path, p_bta_fs_cfg->max_path_len+1, p_root_path, p_bta_fs_cfg->max_path_len);
+ p_buf->p_root_path[p_bta_fs_cfg->max_path_len] = '\0';
+ }
+
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_PbsDisable
+**
+** Description Disable the Phone book access server. If the server is currently
+** connected to a peer device the connection will be closed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsDisable(void)
+{
+ BT_HDR *p_buf;
+
+ bta_sys_deregister(BTA_ID_PBS);
+ if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_PBS_API_DISABLE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+/*******************************************************************************
+**
+** Function BTA_PbsAuthRsp
+**
+** Description Respond to obex client authenticate repond by sending back password to
+** BTA. Called in response to an BTA_PBS_AUTH_EVT event.
+** Used when "enable_authen" is set to TRUE in BTA_PbapsEnable().
+**
+** Note: If the "userid_required" is TRUE in the BTA_PBS_AUTH_EVT
+** event, then p_userid is required, otherwise it is optional.
+**
+** p_password must be less than BTA_PBS_MAX_AUTH_KEY_SIZE (16 bytes)
+** p_userid must be less than OBX_MAX_REALM_LEN (defined in target.h)
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsAuthRsp (char *p_password, char *p_userid)
+{
+ tBTA_PBS_API_AUTHRSP *p_auth_rsp;
+
+ if ((p_auth_rsp = (tBTA_PBS_API_AUTHRSP *)GKI_getbuf(sizeof(tBTA_PBS_API_AUTHRSP))) != NULL)
+ {
+ memset(p_auth_rsp, 0, sizeof(tBTA_PBS_API_AUTHRSP));
+
+ p_auth_rsp->hdr.event = BTA_PBS_API_AUTHRSP_EVT;
+
+ if (p_password)
+ {
+ p_auth_rsp->key_len = strlen(p_password);
+ if (p_auth_rsp->key_len > BTA_PBS_MAX_AUTH_KEY_SIZE)
+ p_auth_rsp->key_len = BTA_PBS_MAX_AUTH_KEY_SIZE;
+ memcpy(p_auth_rsp->key, p_password, p_auth_rsp->key_len);
+ }
+
+ if (p_userid)
+ {
+ p_auth_rsp->userid_len = strlen(p_userid);
+ if (p_auth_rsp->userid_len > OBX_MAX_REALM_LEN)
+ p_auth_rsp->userid_len = OBX_MAX_REALM_LEN;
+ memcpy(p_auth_rsp->userid, p_userid, p_auth_rsp->userid_len);
+ }
+
+ bta_sys_sendmsg(p_auth_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_PbsAccessRsp
+**
+** Description Sends a reply to an access request event (BTA_PBS_ACCESS_EVT).
+** This call MUST be made whenever the event occurs.
+**
+** Parameters oper - operation being accessed.
+** access - BTA_PBS_ACCESS_ALLOW or BTA_PBS_ACCESS_FORBID
+** p_name - path of file or directory to be accessed.
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsAccessRsp(tBTA_PBS_OPER oper, tBTA_PBS_ACCESS_TYPE access, char *p_name)
+{
+ tBTA_PBS_API_ACCESSRSP *p_acc_rsp;
+ UINT16 max_full_name = p_bta_fs_cfg->max_path_len + p_bta_fs_cfg->max_file_len + 1;
+
+ if ((p_acc_rsp = (tBTA_PBS_API_ACCESSRSP *)GKI_getbuf((UINT16)(sizeof(tBTA_PBS_API_ACCESSRSP)
+ + max_full_name + 1))) != NULL)
+ {
+ p_acc_rsp->flag = access;
+ p_acc_rsp->oper = oper;
+ p_acc_rsp->p_name = (char *)(p_acc_rsp + 1);
+ if (p_name)
+ {
+ BCM_STRNCPY_S(p_acc_rsp->p_name, max_full_name+1, p_name, max_full_name);
+ p_acc_rsp->p_name[max_full_name] = '\0';
+ }
+ else
+ p_acc_rsp->p_name[0] = '\0';
+
+ p_acc_rsp->hdr.event = BTA_PBS_API_ACCESSRSP_EVT;
+ bta_sys_sendmsg(p_acc_rsp);
+ }
+}
+
+/*******************************************************************************
+**
+** Function BTA_PbsClose
+**
+** Description Close the current connection.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void BTA_PbsClose(void)
+{
+ BT_HDR *p_buf;
+
+ if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+ {
+ p_buf->event = BTA_PBS_API_CLOSE_EVT;
+ bta_sys_sendmsg(p_buf);
+ }
+}
+
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_cfg.c b/bta/pb/bta_pbs_cfg.c
new file mode 100644
index 0000000..0dc303c
--- /dev/null
+++ b/bta/pb/bta_pbs_cfg.c
@@ -0,0 +1,38 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the BTA Phone Book Access Server.
+**
+** Copyright (c) 2003-2005, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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_ci.c b/bta/pb/bta_pbs_ci.c
new file mode 100644
index 0000000..fa2644b
--- /dev/null
+++ b/bta/pb/bta_pbs_ci.c
@@ -0,0 +1,119 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_ci.c
+**
+** Description: This is the implementation file for the phone book access server
+** call-in functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_pbs_ci.h"
+#include "bta_pbs_int.h"
+#include "gki.h"
+
+/*******************************************************************************
+**
+** Function bta_pbs_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_pbs_co_read() call-out function.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_pbs_ci_open call-in function.
+** num_bytes_read - number of bytes read into the buffer
+** specified in the read callout-function.
+** status - BTA_PBS_CO_OK if get buffer of data,
+** BTA_PBS_CO_FAIL if an error has occurred.
+** final - indicate whether it is the final data
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_read(int fd, UINT16 num_bytes_read,
+ tBTA_PBS_CO_STATUS status, BOOLEAN final)
+{
+ tBTA_PBS_CI_READ_EVT *p_evt;
+
+ if ((p_evt = (tBTA_PBS_CI_READ_EVT *) GKI_getbuf(sizeof(tBTA_PBS_CI_READ_EVT))) != NULL)
+ {
+ p_evt->hdr.event = BTA_PBS_CI_READ_EVT;
+ p_evt->fd = fd;
+ p_evt->status = status;
+ p_evt->num_read = num_bytes_read;
+ p_evt->final = final;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_open
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished opening a pb for reading.
+**
+** Parameters fd - file descriptor passed to the stack in the
+** bta_pbs_ci_open call-in function.
+** status - BTA_PBS_CO_OK if file was opened in mode specified
+** in the call-out function.
+** BTA_PBS_CO_EACCES if the file exists, but contains
+** the wrong access permissions.
+** BTA_PBS_CO_FAIL if any other error has occurred.
+** file_size - The total size of the file
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_ci_open(int fd, tBTA_PBS_CO_STATUS status, UINT32 file_size)
+{
+ tBTA_PBS_CI_OPEN_EVT *p_evt;
+
+ if ((p_evt = (tBTA_PBS_CI_OPEN_EVT *) GKI_getbuf(sizeof(tBTA_PBS_CI_OPEN_EVT))) != NULL)
+ {
+ p_evt->hdr.event = BTA_PBS_CI_OPEN_EVT;
+ p_evt->fd = fd;
+ p_evt->status = status;
+ p_evt->file_size = file_size;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_ci_getvlist
+**
+** Description This function sends an event to BTA indicating the phone has
+** finished reading a VCard list entry.
+**
+** Parameters
+** status - BTA_PBS_CO_OK if reading Vcard list entry
+** BTA_PBS_CO_FAIL if any other error has occurred.
+** final - whether it is the last entry
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BTA_API extern void bta_pbs_ci_getvlist(tBTA_PBS_CO_STATUS status, BOOLEAN final)
+{
+ tBTA_PBS_CI_VLIST_EVT *p_evt;
+
+ if ((p_evt = (tBTA_PBS_CI_VLIST_EVT *) GKI_getbuf(sizeof(tBTA_PBS_CI_VLIST_EVT))) != NULL)
+ {
+ p_evt->hdr.event = BTA_PBS_CI_VLIST_EVT;
+ p_evt->status = status;
+ p_evt->final = final;
+
+ bta_sys_sendmsg(p_evt);
+ }
+}
diff --git a/bta/pb/bta_pbs_int.h b/bta/pb/bta_pbs_int.h
new file mode 100644
index 0000000..19045fd
--- /dev/null
+++ b/bta/pb/bta_pbs_int.h
@@ -0,0 +1,305 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_int.h
+**
+** Description: This is the private file for the phone book access
+** server (PBS).
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#ifndef BTA_PBS_INT_H
+#define BTA_PBS_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_pbs_api.h"
+#include "bta_pbs_co.h"
+#include "bta_pbs_ci.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 */
+
+#define BTA_PBS_GETVCARD_LISTING_TYPE "x-bt/vcard-listing"
+#define BTA_PBS_GETFILE_TYPE "x-bt/phonebook"
+#define BTA_PBS_GETVARD_ENTRY_TYPE "x-bt/vcard"
+#define BTA_PBS_PULLPB_NAME "telecom/pb.vcf"
+#define BTA_PBS_PULLICH_NAME "telecom/ich.vcf"
+#define BTA_PBS_PULLOCH_NAME "telecom/och.vcf"
+#define BTA_PBS_PULLMCH_NAME "telecom/mch.vcf"
+#define BTA_PBS_PULLCCH_NAME "telecom/cch.vcf"
+#define BTA_PBS_PBFOLDER_NAME "pb"
+#define BTA_PBS_ICHFOLDER_NAME "ich"
+#define BTA_PBS_OCHFOLDER_NAME "och"
+#define BTA_PBS_MCHFOLDER_NAME "mch"
+#define BTA_PBS_CCHFOLDER_NAME "cch"
+
+/* Tags for application parameter obex headers */
+/* application parameter len: number of bytes + 2 (tag&len) */
+#define BTA_PBS_TAG_ORDER 1 /* UINT8 */
+#define BTA_PBS_TAG_SEARCH_VALUE 2 /* string */
+#define BTA_PBS_TAG_SEARCH_ATTRIBUTE 3 /* UINT8 */
+#define BTA_PBS_TAG_MAX_LIST_COUNT 4 /* UINT16 */
+#define BTA_PBS_TAG_LIST_START_OFFSET 5 /* UINT16 */
+#define BTA_PBS_TAG_FILTER 6 /* UINT32 */
+#define BTA_PBS_TAG_FORMAT 7 /* UINT8 */
+#define BTA_PBS_TAG_PB_SIZE 8 /* UINT16 */
+#define BTA_PBS_TAG_NEW_MISSED_CALLS 9 /* UINT8 */
+
+#define BTA_PBS_MAX_LIST_COUNT 65535
+
+typedef tOBX_STATUS (tBTA_PBS_OBX_RSP) (tOBX_HANDLE handle, UINT8 rsp_code, BT_HDR *p_pkt);
+
+/* state machine events */
+enum
+{
+ /* these events are handled by the state machine */
+ BTA_PBS_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_PBS),
+
+ BTA_PBS_API_AUTHRSP_EVT, /* Response to password request */
+ BTA_PBS_API_ACCESSRSP_EVT, /* Response to an access request */
+ BTA_PBS_API_CLOSE_EVT, /* Response to a close request */
+ BTA_PBS_CI_READ_EVT, /* Response to Read request */
+ BTA_PBS_CI_OPEN_EVT, /* Response to File Open request */
+ BTA_PBS_CI_VLIST_EVT, /* Response to Get Vcard Entry request */
+ BTA_PBS_OBX_CONN_EVT, /* OBX Channel Connect Request */
+ BTA_PBS_OBX_DISC_EVT, /* OBX Channel Disconnect */
+ BTA_PBS_OBX_ABORT_EVT, /* OBX_operation aborted */
+ BTA_PBS_OBX_PASSWORD_EVT, /* OBX password requested */
+ BTA_PBS_OBX_CLOSE_EVT, /* OBX Channel Disconnected (Link Lost) */
+ BTA_PBS_OBX_GET_EVT, /* Read file data or folder listing */
+ BTA_PBS_OBX_SETPATH_EVT, /* Make or Change Directory */
+ BTA_PBS_APPL_TOUT_EVT, /* Timeout waiting for application */
+ BTA_PBS_DISC_ERR_EVT, /* Sends OBX_DisconnectRsp with error code */
+ BTA_PBS_GASP_ERR_EVT, /* Sends Err Resp to Get, Abort, Setpath */
+ BTA_PBS_CLOSE_CMPL_EVT, /* Finished closing channel */
+
+ /* these events are handled outside the state machine */
+ BTA_PBS_API_ENABLE_EVT
+};
+
+typedef UINT16 tBTA_PBS_INT_EVT;
+
+typedef UINT8 tBTA_PBS_STATE;
+
+/* data type for BTA_PBS_API_ENABLE_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_PBS_CBACK *p_cback;
+ char servicename[BTA_SERVICE_NAME_LEN + 1];
+ char *p_root_path;
+ UINT8 realm [OBX_MAX_REALM_LEN]; /* The realm is intended to be
+ displayed to users so they know
+ which userid and password to use.
+ The first byte of the string is
+ the character set of the string.
+ */
+ UINT8 realm_len;
+ UINT8 sec_mask;
+ UINT8 app_id;
+ BOOLEAN auth_enabled;
+} tBTA_PBS_API_ENABLE;
+
+/* data type for BTA_PBS_API_AUTHRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ UINT8 key [BTA_PBS_MAX_AUTH_KEY_SIZE]; /* The authentication key.*/
+ UINT8 key_len;
+ UINT8 userid [OBX_MAX_REALM_LEN]; /* The authentication user id.*/
+ UINT8 userid_len;
+} tBTA_PBS_API_AUTHRSP;
+
+/* data type for BTA_PBS_API_ACCESSRSP_EVT */
+typedef struct
+{
+ BT_HDR hdr;
+ char *p_name;
+ tBTA_PBS_OPER oper;
+ tBTA_PBS_ACCESS_TYPE flag;
+} tBTA_PBS_API_ACCESSRSP;
+
+typedef struct
+{
+ BT_HDR hdr;
+ UINT32 file_size;
+ int fd;
+ tBTA_PBS_CO_STATUS status;
+} tBTA_PBS_CI_OPEN_EVT;
+
+/* Read Ready Event */
+typedef struct
+{
+ BT_HDR hdr;
+ int fd;
+ UINT16 num_read;
+ tBTA_PBS_CO_STATUS status;
+ BOOLEAN final;
+} tBTA_PBS_CI_READ_EVT;
+
+/* Get Vlist Entry Ready Event */
+typedef struct
+{
+ BT_HDR hdr;
+ tBTA_PBS_CO_STATUS status;
+ BOOLEAN final;
+} tBTA_PBS_CI_VLIST_EVT;
+
+
+/* data type for all obex events
+ hdr.event contains the PBS event
+*/
+typedef struct
+{
+ BT_HDR hdr;
+ tOBX_HANDLE handle;
+ tOBX_EVT_PARAM param;
+ BT_HDR *p_pkt;
+ tOBX_EVENT obx_event;
+ UINT8 rsp_code;
+} tBTA_PBS_OBX_EVENT;
+
+/* union of all event data types */
+typedef union
+{
+ BT_HDR hdr;
+ tBTA_PBS_API_ENABLE api_enable;
+ tBTA_PBS_API_AUTHRSP auth_rsp;
+ tBTA_PBS_API_ACCESSRSP access_rsp;
+ tBTA_PBS_OBX_EVENT obx_evt;
+ tBTA_PBS_CI_OPEN_EVT open_evt;
+ tBTA_PBS_CI_READ_EVT read_evt;
+ tBTA_PBS_CI_VLIST_EVT vlist_evt;
+} tBTA_PBS_DATA;
+
+
+/* OBX Response Packet Structure - Holds current response packet info */
+typedef struct
+{
+ BT_HDR *p_pkt; /* (Get/Put) Holds the current OBX header for Put or Get */
+ UINT8 *p_start; /* (Get/Put) Start of the Body of the packet */
+ UINT16 offset; /* (Get/Put) Contains the current offset into the Body (p_start) */
+ UINT16 bytes_left; /* (Get/Put) Holds bytes available left in Obx packet */
+ BOOLEAN final_pkt; /* (Put) Holds the final bit of the Put packet */
+} tBTA_PBS_OBX_PKT;
+
+
+/* PBS control block */
+typedef struct
+{
+ tBTA_PBS_CBACK *p_cback; /* pointer to application callback function */
+ char *p_name; /* Holds name of current operation */
+ char *p_path; /* Holds path of current operation */
+ char *p_rootpath;
+ char *p_workdir; /* Current working directory */
+ UINT8 *p_stream_indexes; /* Contains pointer to beginning of phonebook size area in ob hdr */
+ tBTA_PBS_OBX_PKT obx; /* Holds the current OBX packet information */
+ tBTA_PBS_PULLPB_APP_PARAMS pullpb_app_params; /* PULLPB Application params */
+ tBTA_PBS_VCARDLIST_APP_PARAMS getvlist_app_params; /* Get VLIST Application params */
+ tBTA_PBS_VCARDLIST vlist; /* Holds current directory list information */
+ UINT32 sdp_handle; /* SDP record handle */
+ UINT32 file_length; /* length of file being PUT/GET */
+ int fd; /* File Descriptor of opened file */
+ BD_ADDR bd_addr; /* Device currently connected to */
+ tOBX_HANDLE obx_handle;
+ UINT16 peer_mtu;
+ UINT16 num_vlist_idxs; /* keeps track of number of indexes in vCard listing */
+ UINT8 scn; /* SCN of the FTP server */
+ tBTA_PBS_STATE state; /* state machine state */
+ UINT8 obx_oper; /* current active OBX operation GET FILE, LISTING, etc */
+ UINT8 app_id;
+ BOOLEAN auth_enabled; /* Is OBEX authentication enabled */
+ BOOLEAN cout_active; /* TRUE when waiting for a call-in function */
+ BOOLEAN aborting;
+ BOOLEAN get_only_indexes; /* True if PCE only wants num indexes for vListing response */
+ tBTA_PBS_OPER acc_active; /* op code when waiting for an access rsp (API) (0 not active) */
+ tBTA_PBS_OBJ_TYPE obj_type;
+ UINT8 realm [OBX_MAX_REALM_LEN]; /* The realm is intended to be
+ displayed to users so they know
+ which userid and password to use.
+ The first byte of the string is
+ the character set of the string.
+ */
+ UINT8 realm_len;
+} tBTA_PBS_CB;
+
+
+
+/* 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
+*****************************************************************************/
+
+/* PBS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_PBS_CB bta_pbs_cb;
+#else
+extern tBTA_PBS_CB *bta_pbs_cb_ptr;
+#define bta_pbs_cb (*bta_pbs_cb_ptr)
+#endif
+
+/* PBS configuration constants */
+extern tBTA_PBS_CFG * p_bta_pbs_cfg;
+
+/*****************************************************************************
+** Function prototypes
+*****************************************************************************/
+
+extern BOOLEAN bta_pbs_hdl_event(BT_HDR *p_msg);
+extern void bta_pbs_sm_execute(tBTA_PBS_CB *p_cb, UINT16 event, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_sdp_register (tBTA_PBS_CB *p_cb, char *p_service_name);
+extern void bta_pbs_obx_cback (tOBX_HANDLE handle, tOBX_EVENT event,
+ tOBX_EVT_PARAM param, BT_HDR *p_pkt);
+
+/* action functions */
+extern void bta_pbs_api_disable(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_api_authrsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_api_accessrsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_api_close(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_connect(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_disc(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_close(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_abort(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_password(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_get(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_obx_setpath(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_appl_tout(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_conn_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_disc_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_gasp_err_rsp(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_close_complete(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_ci_open_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_ci_read_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+extern void bta_pbs_ci_vlist_act(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+/* object store */
+extern void bta_pbs_proc_get_file(char *p_name, tBTA_PBS_OPER operation);
+extern void bta_pbs_req_app_access (tBTA_PBS_OPER oper, tBTA_PBS_CB *p_cb);
+extern void bta_pbs_getvlist(char *p_name);
+/* miscellaneous functions */
+extern void bta_pbs_get_file_rsp(UINT8 rsp_code, UINT16 num_read);
+extern void bta_pbs_clean_getput(tBTA_PBS_CB *p_cb, BOOLEAN is_aborted);
+extern void bta_pbs_end_of_list(UINT8 rsp_code);
+extern UINT8 bta_pbs_add_list_entry(void);
+extern UINT8 bta_pbs_chdir(BT_HDR *p_pkt, BOOLEAN backup_flag, tBTA_PBS_OPER *p_op);
+extern UINT8 * bta_pbs_read_app_params(BT_HDR *p_pkt, UINT8 tag, UINT16 *param_len);
+
+#endif /* BTA_PBS_INT_H */
diff --git a/bta/pb/bta_pbs_main.c b/bta/pb/bta_pbs_main.c
new file mode 100644
index 0000000..1ed892d
--- /dev/null
+++ b/bta/pb/bta_pbs_main.c
@@ -0,0 +1,515 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_main.c
+**
+** Description: This file contains the phone book access server main functions
+** and state machine.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_fs_api.h"
+#include "bta_pbs_api.h"
+#include "bta_pbs_int.h"
+#include "gki.h"
+#include "utl.h"
+#include "obx_api.h"
+#include "rfcdefs.h" /* BT_PSM_RFCOMM */
+#include "bta_fs_co.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+ BTA_PBS_IDLE_ST = 0, /* Idle */
+ BTA_PBS_LISTEN_ST, /* Listen - waiting for OBX/RFC connection */
+ BTA_PBS_W4_AUTH_ST, /* Wait for Authentication - (optional) */
+ BTA_PBS_CONN_ST, /* Connected - PBS Session is active */
+ BTA_PBS_CLOSING_ST /* Closing is in progress */
+};
+
+/* state machine action enumeration list */
+enum
+{
+ BTA_PBS_API_DISABLE,
+ BTA_PBS_API_AUTHRSP,
+ BTA_PBS_API_ACCESSRSP,
+ BTA_PBS_API_CLOSE,
+ BTA_PBS_CI_READ,
+ BTA_PBS_CI_OPEN,
+ BTA_PBS_CI_VLIST,
+ BTA_PBS_OBX_CONNECT,
+ BTA_PBS_OBX_DISC,
+ BTA_PBS_OBX_CLOSE,
+ BTA_PBS_OBX_ABORT,
+ BTA_PBS_OBX_PASSWORD,
+ BTA_PBS_OBX_GET,
+ BTA_PBS_OBX_SETPATH,
+ BTA_PBS_APPL_TOUT,
+ BTA_PBS_CONN_ERR_RSP,
+ BTA_PBS_DISC_ERR_RSP,
+ BTA_PBS_GASP_ERR_RSP,
+ BTA_PBS_CLOSE_COMPLETE,
+ BTA_PBS_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_PBS_ACTION)(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data);
+
+/* action function list */
+const tBTA_PBS_ACTION bta_pbs_action[] =
+{
+ bta_pbs_api_disable,
+ bta_pbs_api_authrsp,
+ bta_pbs_api_accessrsp,
+ bta_pbs_api_close,
+ bta_pbs_ci_read_act,
+ bta_pbs_ci_open_act,
+ bta_pbs_ci_vlist_act,
+ bta_pbs_obx_connect,
+ bta_pbs_obx_disc,
+ bta_pbs_obx_close,
+ bta_pbs_obx_abort,
+ bta_pbs_obx_password,
+ bta_pbs_obx_get,
+ bta_pbs_obx_setpath,
+ bta_pbs_appl_tout,
+ bta_pbs_conn_err_rsp,
+ bta_pbs_disc_err_rsp,
+ bta_pbs_gasp_err_rsp,
+ bta_pbs_close_complete
+};
+
+
+/* state table information */
+#define BTA_PBS_ACTIONS 1 /* number of actions */
+#define BTA_PBS_NEXT_STATE 1 /* position of next state */
+#define BTA_PBS_NUM_COLS 2 /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_pbs_st_idle[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_ENABLE_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST}
+};
+
+/* state table for obex/rfcomm connection state */
+static const UINT8 bta_pbs_st_listen[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_DISABLE_EVT */ {BTA_PBS_API_DISABLE, BTA_PBS_IDLE_ST},
+/* BTA_PBS_API_AUTHRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_API_ACCESSRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_API_CLOSE_EVT */ {BTA_PBS_API_CLOSE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_READ_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_OPEN_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_VLIST_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_CONN_EVT */ {BTA_PBS_OBX_CONNECT, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_DISC_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_ABORT_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_PASSWORD_EVT */ {BTA_PBS_OBX_PASSWORD, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_CLOSE_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_GET_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_SETPATH_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_APPL_TOUT_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_DISC_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_GASP_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CLOSE_CMPL_EVT */ {BTA_PBS_IGNORE, BTA_PBS_LISTEN_ST}
+};
+
+/* state table for wait for authentication response state */
+static const UINT8 bta_pbs_st_w4_auth[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_DISABLE_EVT */ {BTA_PBS_API_DISABLE, BTA_PBS_IDLE_ST},
+/* BTA_PBS_API_AUTHRSP_EVT */ {BTA_PBS_API_AUTHRSP, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_API_ACCESSRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_API_CLOSE_EVT */ {BTA_PBS_API_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_CI_READ_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_CI_OPEN_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_CI_VLIST_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_CONN_EVT */ {BTA_PBS_CONN_ERR_RSP, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_DISC_EVT */ {BTA_PBS_OBX_DISC, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_ABORT_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_PASSWORD_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_CLOSE_EVT */ {BTA_PBS_OBX_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_GET_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_SETPATH_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_APPL_TOUT_EVT */ {BTA_PBS_APPL_TOUT, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_DISC_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_GASP_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_CLOSE_CMPL_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_pbs_st_connected[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_DISABLE_EVT */ {BTA_PBS_API_DISABLE, BTA_PBS_IDLE_ST},
+/* BTA_PBS_API_AUTHRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CONN_ST},
+/* BTA_PBS_API_ACCESSRSP_EVT */ {BTA_PBS_API_ACCESSRSP, BTA_PBS_CONN_ST},
+/* BTA_PBS_API_CLOSE_EVT */ {BTA_PBS_API_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_CI_READ_EVT */ {BTA_PBS_CI_READ, BTA_PBS_CONN_ST},
+/* BTA_PBS_CI_OPEN_EVT */ {BTA_PBS_CI_OPEN, BTA_PBS_CONN_ST},
+/* BTA_PBS_CI_VLIST_EVT */ {BTA_PBS_CI_VLIST, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_CONN_EVT */ {BTA_PBS_CONN_ERR_RSP, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_DISC_EVT */ {BTA_PBS_OBX_DISC, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_ABORT_EVT */ {BTA_PBS_OBX_ABORT, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_PASSWORD_EVT */ {BTA_PBS_IGNORE, BTA_PBS_W4_AUTH_ST},
+/* BTA_PBS_OBX_CLOSE_EVT */ {BTA_PBS_OBX_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_GET_EVT */ {BTA_PBS_OBX_GET, BTA_PBS_CONN_ST},
+/* BTA_PBS_OBX_SETPATH_EVT */ {BTA_PBS_OBX_SETPATH, BTA_PBS_CONN_ST},
+/* BTA_PBS_APPL_TOUT_EVT */ {BTA_PBS_APPL_TOUT, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_DISC_ERR_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CONN_ST},
+/* BTA_PBS_GASP_ERR_EVT */ {BTA_PBS_GASP_ERR_RSP, BTA_PBS_CONN_ST},
+/* BTA_PBS_CLOSE_CMPL_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CONN_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_pbs_st_closing[][BTA_PBS_NUM_COLS] =
+{
+/* Event Action 1 Next state */
+/* BTA_PBS_API_DISABLE_EVT */ {BTA_PBS_API_DISABLE, BTA_PBS_IDLE_ST},
+/* BTA_PBS_API_AUTHRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_API_ACCESSRSP_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_API_CLOSE_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_CI_READ_EVT */ {BTA_PBS_CLOSE_COMPLETE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_OPEN_EVT */ {BTA_PBS_CLOSE_COMPLETE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_CI_VLIST_EVT */ {BTA_PBS_CLOSE_COMPLETE, BTA_PBS_LISTEN_ST},
+/* BTA_PBS_OBX_CONN_EVT */ {BTA_PBS_CONN_ERR_RSP, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_DISC_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_ABORT_EVT */ {BTA_PBS_OBX_ABORT, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_PASSWORD_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_CLOSE_EVT */ {BTA_PBS_OBX_CLOSE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_GET_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_OBX_SETPATH_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_APPL_TOUT_EVT */ {BTA_PBS_IGNORE, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_DISC_ERR_EVT */ {BTA_PBS_DISC_ERR_RSP, BTA_PBS_CONN_ST},
+/* BTA_PBS_GASP_ERR_EVT */ {BTA_PBS_GASP_ERR_RSP, BTA_PBS_CLOSING_ST},
+/* BTA_PBS_CLOSE_CMPL_EVT */ {BTA_PBS_CLOSE_COMPLETE, BTA_PBS_LISTEN_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_PBS_ST_TBL)[BTA_PBS_NUM_COLS];
+
+/* state table */
+const tBTA_PBS_ST_TBL bta_pbs_st_tbl[] =
+{
+ bta_pbs_st_idle,
+ bta_pbs_st_listen,
+ bta_pbs_st_w4_auth,
+ bta_pbs_st_connected,
+ bta_pbs_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* PBS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_PBS_CB bta_pbs_cb;
+#endif
+
+#if BTA_PBS_DEBUG == TRUE
+static char *pbs_evt_code(tBTA_PBS_INT_EVT evt_code);
+static char *pbs_state_code(tBTA_PBS_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function bta_pbs_sm_execute
+**
+** Description State machine event handling function for PBS
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_sm_execute(tBTA_PBS_CB *p_cb, UINT16 event, tBTA_PBS_DATA *p_data)
+{
+ tBTA_PBS_ST_TBL state_table;
+ UINT8 action;
+ int i;
+ tBTA_PBS_OBX_EVENT *p_obex_event;
+#if BTA_PBS_DEBUG == TRUE
+ tBTA_PBS_STATE in_state = bta_pbs_cb.state;
+ UINT16 in_event = event;
+ APPL_TRACE_EVENT3("PBS Event : State 0x%02x [%s], Event [%s]", in_state,
+ pbs_state_code(in_state),
+ pbs_evt_code(event));
+#endif
+
+ /* look up the state table for the current state */
+ state_table = bta_pbs_st_tbl[p_cb->state];
+
+ event &= 0x00FF;
+
+ /* set next state */
+ p_cb->state = state_table[event][BTA_PBS_NEXT_STATE];
+
+ /* execute action functions */
+ for (i = 0; i < BTA_PBS_ACTIONS; i++)
+ {
+ if ((action = state_table[event][i]) != BTA_PBS_IGNORE)
+ {
+ (*bta_pbs_action[action])(p_cb, p_data);
+ }
+ else
+ {
+ if (event >= BTA_PBS_OBX_CONN_EVT && event <= BTA_PBS_OBX_SETPATH_EVT) {
+ p_obex_event = (tBTA_PBS_OBX_EVENT *) p_data;
+ utl_freebuf((void**)&(p_obex_event->p_pkt));
+ }
+ break;
+ }
+ }
+
+#if BTA_PBS_DEBUG == TRUE
+ if (in_state != bta_pbs_cb.state)
+ {
+ APPL_TRACE_DEBUG3("PBS State Change: [%s] -> [%s] after Event [%s]",
+ pbs_state_code(in_state),
+ pbs_state_code(bta_pbs_cb.state),
+ pbs_evt_code(in_event));
+ }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_api_enable
+**
+** Description Handle an api enable event. This function enables the PBS
+** Server by opening an Obex/Rfcomm channel and placing it into
+** listen mode.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void bta_pbs_api_enable(tBTA_PBS_CB *p_cb, tBTA_PBS_DATA *p_data)
+{
+ tOBX_StartParams start_msg;
+ tBTA_PBS_API_ENABLE *p_api = &p_data->api_enable;
+ tOBX_TARGET target;
+ UINT16 len;
+ tOBX_STATUS status;
+ tBTA_UTL_COD cod;
+
+ /* initialize control block */
+ memset(p_cb, 0, sizeof(tBTA_PBS_CB));
+
+ /* Allocate an aligned memory buffer to hold the root path and working directory */
+ /* Add 1 byte for '\0' */
+ len = p_bta_fs_cfg->max_path_len + 1;
+ if ((p_cb->p_rootpath = (char *)GKI_getbuf((UINT16)(len * 2))) != NULL)
+ {
+ p_cb->p_workdir = p_cb->p_rootpath + len;
+ memcpy(target.target, BTA_PBS_TARGET_UUID, BTA_PBS_UUID_LENGTH);
+ target.len = BTA_PBS_UUID_LENGTH;
+
+ /* store parameters */
+ p_cb->app_id = p_api->app_id;
+ p_cb->p_cback = p_api->p_cback;
+ p_cb->scn = BTM_AllocateSCN();
+ p_cb->auth_enabled = p_api->auth_enabled;
+ p_cb->fd = BTA_FS_INVALID_FD;
+ p_cb->realm_len = p_api->realm_len;
+ memcpy(p_cb->realm, p_api->realm, p_api->realm_len);
+
+ /* Initialize the current working directory to be the root directory */
+ BCM_STRNCPY_S(p_cb->p_rootpath, len, p_api->p_root_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_rootpath[len-1] = '\0';
+ BCM_STRNCPY_S(p_cb->p_workdir, len, p_api->p_root_path, p_bta_fs_cfg->max_path_len);
+ p_cb->p_workdir[len-1] = '\0';
+
+ /* Register PBS security requirements with BTM */
+ BTM_SetSecurityLevel(FALSE, p_api->servicename, BTM_SEC_SERVICE_PBAP,
+ p_api->sec_mask, BT_PSM_RFCOMM,
+ BTM_SEC_PROTO_RFCOMM, (UINT32)p_cb->scn);
+
+ /* Start up the PBS service */
+ memset (&start_msg, 0, sizeof(tOBX_StartParams));
+ start_msg.p_target = &target;
+
+ /* Make the MTU fit into one RFC frame */
+ start_msg.mtu = OBX_MAX_MTU;
+ start_msg.scn = p_cb->scn;
+ start_msg.authenticate = p_cb->auth_enabled;
+
+ start_msg.auth_option = (p_bta_pbs_cfg->userid_req) ? OBX_AO_USR_ID : OBX_AO_NONE;
+ start_msg.p_cback = bta_pbs_obx_cback;
+
+ start_msg.realm_len = p_api->realm_len;
+ start_msg.p_realm = p_api->realm;
+ start_msg.realm_charset = (tOBX_CHARSET) p_bta_pbs_cfg->realm_charset;
+
+ if ((status = OBX_StartServer (&start_msg, &p_cb->obx_handle)) == OBX_SUCCESS)
+ {
+ p_cb->state = BTA_PBS_LISTEN_ST;
+
+ /* Set the File Transfer service class bit */
+ cod.service = BTM_COD_SERVICE_OBJ_TRANSFER;
+ utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+
+ /* Set up the SDP record for pbs service */
+ bta_pbs_sdp_register(p_cb, p_api->servicename);
+ }
+ else
+ APPL_TRACE_ERROR1("OBX_StartServer returns error (%d)", status);
+ }
+ else /* Cannot allocate resources to run Server */
+ APPL_TRACE_ERROR0("Not enough Resources to run PBS Server");
+
+ p_cb->p_cback(BTA_PBS_ENABLE_EVT, 0);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_hdl_event
+**
+** Description File transfer server main event handling function.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+BOOLEAN bta_pbs_hdl_event(BT_HDR *p_msg)
+{
+#if BTA_PBS_DEBUG == TRUE
+ tBTA_PBS_STATE in_state = bta_pbs_cb.state;
+#endif
+
+ switch (p_msg->event)
+ {
+ case BTA_PBS_API_ENABLE_EVT:
+#if BTA_PBS_DEBUG == TRUE
+ APPL_TRACE_EVENT3("PBS Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+ pbs_state_code(in_state),
+ pbs_evt_code(p_msg->event));
+#endif
+ bta_pbs_api_enable(&bta_pbs_cb, (tBTA_PBS_DATA *) p_msg);
+
+#if BTA_PBS_DEBUG == TRUE
+ if (in_state != bta_pbs_cb.state)
+ {
+ APPL_TRACE_DEBUG3("PBS State Change: [%s] -> [%s] after Event [%s]",
+ pbs_state_code(in_state),
+ pbs_state_code(bta_pbs_cb.state),
+ pbs_evt_code(p_msg->event));
+ }
+#endif
+ break;
+
+ default:
+ bta_pbs_sm_execute(&bta_pbs_cb, p_msg->event, (tBTA_PBS_DATA *) p_msg);
+ break;
+ }
+
+ return (TRUE);
+}
+
+
+/*****************************************************************************
+** Debug Functions
+*****************************************************************************/
+#if BTA_PBS_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function pbs_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *pbs_evt_code(tBTA_PBS_INT_EVT evt_code)
+{
+ switch(evt_code)
+ {
+ case BTA_PBS_API_DISABLE_EVT:
+ return "BTA_PBS_API_DISABLE_EVT";
+ case BTA_PBS_API_AUTHRSP_EVT:
+ return "BTA_PBS_API_AUTHRSP_EVT";
+ case BTA_PBS_API_ACCESSRSP_EVT:
+ return "BTA_PBS_API_ACCESSRSP_EVT";
+ case BTA_PBS_API_CLOSE_EVT:
+ return "BTA_PBS_API_CLOSE_EVT";
+ case BTA_PBS_CI_READ_EVT:
+ return "BTA_PBS_CI_READ_EVT";
+ case BTA_PBS_CI_OPEN_EVT:
+ return "BTA_PBS_CI_OPEN_EVT";
+ case BTA_PBS_CI_VLIST_EVT:
+ return "BTA_PBS_CI_VLIST_EVT";
+ case BTA_PBS_OBX_CONN_EVT:
+ return "BTA_PBS_OBX_CONN_EVT";
+ case BTA_PBS_OBX_DISC_EVT:
+ return "BTA_PBS_OBX_DISC_EVT";
+ case BTA_PBS_OBX_ABORT_EVT:
+ return "BTA_PBS_OBX_ABORT_EVT";
+ case BTA_PBS_OBX_PASSWORD_EVT:
+ return "BTA_PBS_OBX_PASSWORD_EVT";
+ case BTA_PBS_OBX_CLOSE_EVT:
+ return "BTA_PBS_OBX_CLOSE_EVT";
+ case BTA_PBS_OBX_GET_EVT:
+ return "BTA_PBS_OBX_GET_EVT";
+ case BTA_PBS_OBX_SETPATH_EVT:
+ return "BTA_PBS_OBX_SETPATH_EVT";
+ case BTA_PBS_APPL_TOUT_EVT:
+ return "BTA_PBS_APPL_TOUT_EVT";
+ case BTA_PBS_DISC_ERR_EVT:
+ return "BTA_PBS_DISC_ERR_EVT";
+ case BTA_PBS_GASP_ERR_EVT:
+ return "BTA_PBS_GASP_ERR_EVT";
+ case BTA_PBS_API_ENABLE_EVT:
+ return "BTA_PBS_API_ENABLE_EVT";
+ case BTA_PBS_CLOSE_CMPL_EVT:
+ return "BTA_PBS_CLOSE_CMPL_EVT";
+ default:
+ APPL_TRACE_EVENT1("unknown PBS Event: %d", evt_code)
+ return "unknown PBS event code";
+ }
+}
+
+/*******************************************************************************
+**
+** Function pbs_evt_code
+**
+** Description
+**
+** Returns void
+**
+*******************************************************************************/
+static char *pbs_state_code(tBTA_PBS_STATE state_code)
+{
+ switch(state_code)
+ {
+ case BTA_PBS_IDLE_ST:
+ return "BTA_PBS_IDLE_ST";
+ case BTA_PBS_LISTEN_ST:
+ return "BTA_PBS_LISTEN_ST";
+ case BTA_PBS_W4_AUTH_ST:
+ return "BTA_PBS_W4_AUTH_ST";
+ case BTA_PBS_CONN_ST:
+ return "BTA_PBS_CONN_ST";
+ case BTA_PBS_CLOSING_ST:
+ return "BTA_PBS_CLOSING_ST";
+ default:
+ return "unknown PBS state code";
+ }
+}
+
+#endif /* Debug Functions */
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_sdp.c b/bta/pb/bta_pbs_sdp.c
new file mode 100644
index 0000000..eeec573
--- /dev/null
+++ b/bta/pb/bta_pbs_sdp.c
@@ -0,0 +1,113 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_sdp.c
+**
+** File: Implements the SDP functions used by Phone Book Access Server
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "sdp_api.h"
+#include "bta_pbs_int.h"
+
+/*****************************************************************************
+** Constants
+*****************************************************************************/
+
+
+/*****************************************************************************
+**
+** Function: bta_pbs_sdp_register()
+**
+** Purpose: Registers the PBS service with SDP
+**
+** Parameters:
+**
+**
+** Returns: void
+**
+*****************************************************************************/
+void bta_pbs_sdp_register (tBTA_PBS_CB *p_cb, char *p_service_name)
+{
+ tSDP_PROTOCOL_ELEM protoList [3];
+ UINT16 pbs_service = UUID_SERVCLASS_PBAP_PSE;
+// btla-specific ++
+ UINT16 browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+// btla-specific --
+ BOOLEAN status = FALSE;
+
+ if ((p_cb->sdp_handle = SDP_CreateRecord()) == 0)
+ {
+ APPL_TRACE_WARNING0("PBS SDP: Unable to register PBS Service");
+ return;
+ }
+
+ /* add service class */
+ if (SDP_AddServiceClassIdList(p_cb->sdp_handle, 1, &pbs_service))
+ {
+ memset( protoList, 0 , 3*sizeof(tSDP_PROTOCOL_ELEM) );
+ /* add protocol list, including RFCOMM scn */
+ protoList[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+ protoList[0].num_params = 0;
+ protoList[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
+ protoList[1].num_params = 1;
+ protoList[1].params[0] = p_cb->scn;
+ protoList[2].protocol_uuid = UUID_PROTOCOL_OBEX;
+ protoList[2].num_params = 0;
+
+ if (SDP_AddProtocolList(p_cb->sdp_handle, 3, protoList))
+ {
+ status = TRUE; /* All mandatory fields were successful */
+
+ /* optional: if name is not "", add a name entry */
+ if (*p_service_name != '\0')
+ SDP_AddAttribute(p_cb->sdp_handle,
+ (UINT16)ATTR_ID_SERVICE_NAME,
+ (UINT8)TEXT_STR_DESC_TYPE,
+ (UINT32)(strlen(p_service_name) + 1),
+ (UINT8 *)p_service_name);
+
+ /* Add in the Bluetooth Profile Descriptor List */
+ SDP_AddProfileDescriptorList(p_cb->sdp_handle,
+ UUID_SERVCLASS_PHONE_ACCESS,
+ BTA_PBS_DEFAULT_VERSION);
+
+ } /* end of setting mandatory protocol list */
+ } /* end of setting mandatory service class */
+
+ /* add supported feature and repositories */
+ if (status)
+ {
+// btla-specific ++
+ // SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
+ // (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_features);
+ SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE,
+ (UINT32)1, (UINT8*)&p_bta_pbs_cfg->supported_repositories);
+
+ /* Make the service browseable */
+ SDP_AddUuidSequence (p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
+// btla-specific --
+ }
+
+ if (!status)
+ {
+ SDP_DeleteRecord(p_cb->sdp_handle);
+ APPL_TRACE_ERROR0("bta_pbs_sdp_register FAILED");
+ }
+ else
+ {
+ bta_sys_add_uuid(pbs_service); /* UUID_SERVCLASS_PBAP_PSE */
+ APPL_TRACE_DEBUG1("PBS: SDP Registered (handle 0x%08x)", p_cb->sdp_handle);
+ }
+
+ return;
+}
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_utils.c b/bta/pb/bta_pbs_utils.c
new file mode 100644
index 0000000..61d7401
--- /dev/null
+++ b/bta/pb/bta_pbs_utils.c
@@ -0,0 +1,734 @@
+/*****************************************************************************
+**
+** Name: bta_pbs_utils.c
+**
+** Description: This file implements utils functions for phone book access
+** server.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include <stdio.h>
+#include <string.h>
+#include "bta_fs_api.h"
+#include "bta_pbs_int.h"
+#include "bta_fs_co.h"
+#include "gki.h"
+#include "utl.h"
+
+/*******************************************************************************
+** Constants
+*******************************************************************************/
+
+/*******************************************************************************
+** Local Function Prototypes
+*******************************************************************************/
+static void bta_pbs_translate_special_character(char *buffer, const char *str);
+/*******************************************************************************
+* Macros for PBS
+*******************************************************************************/
+#define BTA_PBS_XML_EOL "\n"
+#define BTA_PBS_FOLDER_LISTING_START ( "<?xml version=\"1.0\"?>\n" \
+ "<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">\n" \
+ "<vCard-listing version=\"1.0\">\n" )
+
+#define BTA_PBS_FOLDER_LISTING_END ( "</vCard-listing>" )
+#define BTA_PBS_PARENT_FOLDER (" <parent-folder/>\n")
+
+#define BTA_PBS_CARD_ELEM "card handle"
+#define BTA_PBS_NAME_ATTR "name"
+
+/*******************************************************************************
+* Exported Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function bta_pbs_getdirlist
+**
+** Description Processes the retrieval of a directory listing.
+**
+** Parameters p_pkt - Pointer to the OBX Get request
+** name directory to list.
+**
+**
+** Returns UINT8 - OBX response code. OBX_RSP_OK if initiated.
+**
+*******************************************************************************/
+void bta_pbs_getvlist(char *p_name)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 temp_len;
+ UINT8 rsp_code = OBX_RSP_OK;
+ UINT16 pb_size, new_missed_call, len=0;
+ UINT8 *p, *p_start;
+ char *p_sep = NULL;
+
+
+ /* if this the first time asking for access */
+ if (!p_cb->p_path)
+ {
+ p_cb->p_path = (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1));
+ /* If not specified, use the current work directory */
+ if (!p_name || p_name[0] == '\0')
+ {
+ BCM_STRNCPY_S(p_cb->p_path, p_bta_fs_cfg->max_path_len+1, p_cb->p_workdir, p_bta_fs_cfg->max_path_len);
+ p_sep = strchr((char *)p_cb->p_path, '/');
+ if (p_sep)
+ *p_sep = p_bta_fs_cfg->path_separator;
+ }
+ else
+ {
+ if ((strlen(p_cb->p_workdir) + strlen(p_name) + 2) <= p_bta_fs_cfg->max_path_len)
+ {
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+ if (p_bta_fs_cfg->path_separator == 0x5c)
+ {
+ while ((p_sep = strchr((char *)p_cb->p_path, '/')) != NULL)
+ {
+ if (p_sep)
+ *p_sep = p_bta_fs_cfg->path_separator;
+ }
+ }
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ if (rsp_code == OBX_RSP_OK)
+ {
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /* p_cb->peer_mtu */ OBX_LRG_DATA_POOL_SIZE);
+ if (p_obx->p_pkt)
+ {
+ /* Notify the application that a get file has been requested */
+ bta_pbs_req_app_access (BTA_PBS_OPER_PULL_VCARD_LIST, p_cb);
+ return;
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_pbs_clean_getput(p_cb, TRUE);
+ }
+ else if (p_cb->p_path)
+ {
+ /* Build the listing */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ if (!p_obx->p_pkt)
+ p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /* p_cb->peer_mtu */ OBX_LRG_DATA_POOL_SIZE);
+ if (p_obx->p_pkt)
+ {
+ /* Is this a new request or continuation? */
+ if ((p_cb->obx_oper == BTA_PBS_OPER_NONE))
+ {
+ p_cb->get_only_indexes = FALSE;
+
+ if (p_cb->getvlist_app_params.max_count == 0 ||
+ p_cb->obj_type == BTA_PBS_MCH_OBJ)
+ {
+ p_start = OBX_AddByteStrStart(p_obx->p_pkt, &len);
+ bta_pbs_co_getpbinfo(p_cb->obx_oper, p_cb->obj_type, &pb_size, &new_missed_call);
+ p = p_start;
+ /* Just looking for number of indexes only ? */
+ if (p_cb->getvlist_app_params.max_count == 0)
+ {
+ *p++ = BTA_PBS_TAG_PB_SIZE;
+ *p++ = 2;
+ p_cb->p_stream_indexes = p; /* save location to store entries later */
+ UINT16_TO_BE_STREAM(p, p_cb->getvlist_app_params.max_count);
+
+ /* overwrite appl params max count so entries will be retrieved */
+ p_cb->getvlist_app_params.max_count = BTA_PBS_MAX_LIST_COUNT;
+ /* ignore the list start offset */
+ p_cb->getvlist_app_params.start_offset = 0;
+ p_cb->get_only_indexes = TRUE;
+ p_cb->num_vlist_idxs = 0;
+ APPL_TRACE_EVENT1("PBS Get Vcard List: Name [p_stream = 0x%07x] (Indexes Only)", /*p_cb->p_path*/(UINT32)p_cb->p_stream_indexes);
+ }
+
+ if (p_cb->obj_type == BTA_PBS_MCH_OBJ)
+ {
+ *p++ = BTA_PBS_TAG_NEW_MISSED_CALLS;
+ *p++ = 1;
+ *p++ = (UINT8) new_missed_call;
+ }
+ OBX_AddByteStrHdr(p_obx->p_pkt, OBX_HI_APP_PARMS, NULL, (UINT16)(p - p_start));
+ }
+
+ /* By pass Body Header if only requesting number of entries */
+ if (!p_cb->get_only_indexes)
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ temp_len = strlen(BTA_PBS_FOLDER_LISTING_START);
+
+ /* Add the beginning label of vard list */
+ memcpy(p_obx->p_start, BTA_PBS_FOLDER_LISTING_START, temp_len);
+ p_obx->bytes_left -= (UINT16)(temp_len + strlen(BTA_PBS_FOLDER_LISTING_END));
+ p_obx->offset += temp_len;
+
+ APPL_TRACE_EVENT1("PBS Get Vcard List: Name [%s]", p_cb->p_path);
+ }
+
+ p_cb->obx_oper = BTA_PBS_OPER_PULL_VCARD_LIST;
+ p_cb->cout_active = TRUE;
+
+ bta_pbs_co_getvlist(p_cb->p_path, &p_cb->getvlist_app_params,
+ TRUE, &p_cb->vlist);
+
+ /* List is not complete, so don't send the response yet */
+ rsp_code = OBX_RSP_PART_CONTENT;
+ }
+ else /* continue case */
+ {
+ /* By pass Body Header if only requesting number of entries */
+ if (!p_cb->get_only_indexes)
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+ APPL_TRACE_EVENT1("PBS Get Vcard List: Name [%s] continue", p_cb->p_path);
+ }
+
+ /* Add the entry previously retrieved */
+ rsp_code = bta_pbs_add_list_entry();
+
+ if (!p_obx->final_pkt) {
+ p_cb->cout_active = TRUE;
+
+ bta_pbs_co_getvlist(p_cb->p_path, &p_cb->getvlist_app_params,
+ FALSE, &p_cb->vlist);
+ /* List is not complete, so don't send the response yet */
+ rsp_code = OBX_RSP_PART_CONTENT;
+ } else
+ p_obx->final_pkt = FALSE;
+ }
+ }
+ else
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+ }
+ }
+ else /* Error occurred */
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+ /* Response goes out if complete or error occurred */
+ if (rsp_code != OBX_RSP_PART_CONTENT)
+ bta_pbs_end_of_list(rsp_code);
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_proc_get_file
+**
+** Description Processes a Get File Operation.
+** If first OBX request, the file is opened, otherwise if it is
+** a continuation the next read is initiated.
+**
+** Parameters p_pkt - Pointer to the OBX Get request
+** name of file to read.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_proc_get_file(char *p_name, tBTA_PBS_OPER operation)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+ char *p_sep;
+
+ if (operation != BTA_PBS_OPER_PULL_PB && operation != BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ return;
+ /* Allocate an OBX packet */
+ if (p_obx->p_pkt != NULL || (p_obx->p_pkt = (BT_HDR *)OBX_HdrInit(p_cb->obx_handle,
+ /*p_cb->peer_mtu*/OBX_LRG_DATA_POOL_SIZE)) != NULL)
+ {
+ /* Is this a new request or continuation? */
+ if ((p_cb->obx_oper == BTA_PBS_OPER_NONE))
+ {
+ /* Validate the name */
+ if (p_name)
+ {
+ if ((p_cb->p_path =
+ (char *)GKI_getbuf((UINT16)(p_bta_fs_cfg->max_path_len + 1))) != NULL)
+ {
+ /* Build a fully qualified path for Pull Vcard entry */
+ if (operation == BTA_PBS_OPER_PULL_VCARD_ENTRY)
+ {
+ if ((strlen(p_cb->p_workdir) + strlen(p_name) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ rsp_code = OBX_RSP_OK;
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+ if (p_bta_fs_cfg->path_separator == 0x5c) {
+ while ((p_sep = strchr((char *)p_cb->p_path, '/')) != NULL)
+ {
+ if (p_sep)
+ *p_sep = p_bta_fs_cfg->path_separator;
+ }
+ }
+
+ APPL_TRACE_EVENT1("PBS PULL VCARD ENTRY: Name [%s]", p_cb->p_path);
+
+ p_cb->obx_oper = BTA_PBS_OPER_PULL_VCARD_ENTRY;
+
+ /* Notify the application that a get file has been requested */
+ bta_pbs_req_app_access (BTA_PBS_OPER_PULL_VCARD_ENTRY, p_cb);
+ }
+ }
+
+ /* Build a fully qualified path for Pull PBentry */
+ if (operation == BTA_PBS_OPER_PULL_PB)
+ {
+ if ((strlen(p_cb->p_rootpath) + strlen(p_name) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ rsp_code = OBX_RSP_OK;
+ sprintf(p_cb->p_path, "%s%c%s", p_cb->p_rootpath,
+ p_bta_fs_cfg->path_separator, p_name);
+ if (p_bta_fs_cfg->path_separator == 0x5c) {
+ while ((p_sep = strchr((char *)p_cb->p_path, '/')) != NULL)
+ {
+ if (p_sep)
+ *p_sep = p_bta_fs_cfg->path_separator;
+ }
+ }
+
+ APPL_TRACE_EVENT1("PBS PULL PB : Name [%s]", p_cb->p_path);
+
+ p_cb->obx_oper = BTA_PBS_OPER_PULL_PB;
+
+ /* Notify the application that a get file has been requested */
+ bta_pbs_req_app_access (BTA_PBS_OPER_PULL_PB, p_cb);
+ }
+ }
+
+ }
+ }
+ }
+ else /* Continue reading from the file */
+ {
+ /* Add the start of the Body Header */
+ p_obx->offset = 0;
+ p_obx->bytes_left = 0;
+ p_obx->p_start = OBX_AddBodyStart(p_obx->p_pkt, &p_obx->bytes_left);
+
+ rsp_code = OBX_RSP_OK;
+ p_cb->cout_active = TRUE;
+ bta_pbs_co_read(p_cb->fd, p_cb->obx_oper, &p_obx->p_start[p_obx->offset],
+ p_obx->bytes_left);
+ }
+ }
+ if (rsp_code != OBX_RSP_OK)
+ bta_pbs_get_file_rsp(rsp_code, 0);
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_chdir
+**
+** Description Changes the current path to the specified directory.
+**
+** Parameters p_pkt - Pointer to the OBX packet
+** backup_flag - if TRUE, path adjusted up one level.
+**
+** Returns UINT8 - OBX response code
+**
+*******************************************************************************/
+UINT8 bta_pbs_chdir(BT_HDR *p_pkt, BOOLEAN backup_flag, tBTA_PBS_OPER *p_op)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ char *p_path;
+ char *p_name;
+ char *p_workdir = p_cb->p_workdir;
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+ BOOLEAN is_dir;
+
+ if (!backup_flag)
+ {
+ p_path = p_cb->p_path;
+ p_name = p_cb->p_name;
+
+ /* If No Name header, or if it is NULL, set to root path */
+ if (*p_name == '\0')
+ {
+ BCM_STRNCPY_S(p_workdir, p_bta_fs_cfg->max_path_len+1, p_cb->p_rootpath, p_bta_fs_cfg->max_path_len);
+ p_workdir[p_bta_fs_cfg->max_path_len] = '\0';
+ p_cb->obj_type = BTA_PBS_NONE_OBJ;
+ rsp_code = OBX_RSP_OK;
+ APPL_TRACE_DEBUG0("PBS: Setting current path to ROOT");
+ }
+ /* Make sure the new path is not too big */
+ else if ((strlen(p_name) + strlen(p_workdir) + 2)
+ <= p_bta_fs_cfg->max_path_len)
+ {
+ if (!strcmp(p_name, "pb") || !strcmp(p_name, "telecom") ||
+ !strcmp(p_name, "ich") || !strcmp(p_name, "och") ||
+ !strcmp(p_name, "mch") || !strcmp(p_name, "cch") ||
+ !strcmp(p_name, "SIM1"))
+ {
+
+ /* create a temporary path for creation attempt */
+ sprintf(p_path, "%s%c%s", p_workdir,
+ p_bta_fs_cfg->path_separator, p_name);
+
+ if (((bta_fs_co_access(p_path, BTA_FS_ACC_EXIST,
+ &is_dir, p_cb->app_id)) == BTA_FS_CO_OK) && is_dir)
+ {
+ *p_op = BTA_PBS_OPER_SET_PB;
+ }
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+ else
+ rsp_code = OBX_RSP_BAD_REQUEST;
+ }
+ }
+ else /* Backing up a directory */
+ {
+ /* Backup a level unless already at root */
+ if (strcmp(p_workdir, p_cb->p_rootpath))
+ {
+ /* Find the last occurrence of separator and replace with '\0' */
+ if ((p_path = strrchr(p_workdir, (int)p_bta_fs_cfg->path_separator)) != NULL)
+ *p_path = '\0';
+ p_cb->obj_type = BTA_PBS_NONE_OBJ;
+ APPL_TRACE_DEBUG1("PBS: SET NEW PATH [%s]", p_cb->p_workdir);
+
+ rsp_code = OBX_RSP_OK;
+ }
+ else
+ rsp_code = OBX_RSP_NOT_FOUND;
+ }
+
+ return (rsp_code);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_end_of_list
+**
+** Description Finishes up the end body of the listing, and sends out the
+** OBX response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_end_of_list(UINT8 rsp_code)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ UINT16 temp_len;
+
+ /* Add the end of folder listing string if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ /* If only getting entries add the number to the response */
+ if (p_cb->get_only_indexes)
+ {
+ if (rsp_code != OBX_RSP_OK)
+ {
+ rsp_code = OBX_RSP_OK;
+ APPL_TRACE_WARNING0("bta_pbs_end_of_list: index ONLY, but received OBX_RSP_CONTINUE??");
+ }
+ APPL_TRACE_DEBUG2("bta_pbs_end_of_list: indexes = %d, p_stream_indexes = 0x%07x",
+ p_cb->num_vlist_idxs, p_cb->p_stream_indexes);
+ UINT16_TO_BE_STREAM(p_cb->p_stream_indexes, p_cb->num_vlist_idxs);
+ }
+ else
+ {
+ /* If listing has completed, add on end string (http) */
+ if (rsp_code == OBX_RSP_OK)
+ {
+ temp_len = strlen(BTA_PBS_FOLDER_LISTING_END);
+ memcpy(&p_obx->p_start[p_obx->offset], BTA_PBS_FOLDER_LISTING_END, temp_len);
+ p_obx->offset += temp_len;
+
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, TRUE);
+ }
+ else /* More listing data to be sent */
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, FALSE);
+ }
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+ if (rsp_code == OBX_RSP_OK)
+ bta_pbs_clean_getput(p_cb, FALSE);
+ }
+ else /* An error occurred */
+ {
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)NULL);
+ bta_pbs_clean_getput(p_cb, TRUE);
+ }
+
+}
+
+/*******************************************************************************
+**
+** Function bta_pbs_get_file_rsp
+**
+** Description Finishes up the end body of the file get, and sends out the
+** OBX response
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_get_file_rsp(UINT8 rsp_code, UINT16 num_read)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ BOOLEAN done = TRUE;
+
+ /* Send the response packet if successful operation */
+ if (rsp_code == OBX_RSP_OK || rsp_code == OBX_RSP_CONTINUE)
+ {
+ p_obx->offset += num_read;
+
+ /* More to be sent */
+ if (rsp_code == OBX_RSP_CONTINUE)
+ {
+ if (p_obx->bytes_left != num_read)
+ APPL_TRACE_WARNING2("PBS Read: Requested (0x%04x), Read In (0x%04x)",
+ p_obx->bytes_left, num_read);
+ done = FALSE;
+ }
+
+ if (num_read)
+ OBX_AddBodyEnd(p_obx->p_pkt, p_obx->p_start, p_obx->offset, done);
+ }
+ else
+ p_cb->obx_oper = BTA_PBS_OPER_NONE;
+
+ OBX_GetRsp(p_cb->obx_handle, rsp_code, (BT_HDR *)p_obx->p_pkt);
+ p_obx->p_pkt = NULL; /* Do not deallocate buffer; OBX will */
+
+ /* Final response packet sent out */
+ if (done && rsp_code == OBX_RSP_OK)
+ bta_pbs_clean_getput(p_cb, FALSE);
+ /* If there is error */
+ if (rsp_code != OBX_RSP_OK && rsp_code != OBX_RSP_CONTINUE)
+ bta_pbs_clean_getput(p_cb, TRUE);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_add_list_entry
+**
+** Description used by bta_pbs_getdirlist to write a list entry to an
+** obex packet (byte array).
+**
+** Returns UINT8 - OBX response code
+** OBX_RSP_OK
+** OBX_RSP_CONTINUE
+** Others send error response out
+**
+*******************************************************************************/
+UINT8 bta_pbs_add_list_entry(void)
+{
+ tBTA_PBS_CB *p_cb = &bta_pbs_cb;
+ tBTA_PBS_OBX_PKT *p_obx = &p_cb->obx;
+ char *p_buf;
+ UINT16 size;
+ UINT8 rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+ /* Skip filling in entry; just counting */
+ if (p_cb->get_only_indexes)
+ {
+ return (OBX_RSP_OK);
+ }
+
+ if ((p_buf = (char *)GKI_getbuf(GKI_MAX_BUF_SIZE)) != NULL)
+ {
+ p_buf[0] = '\0';
+
+ APPL_TRACE_DEBUG2("bta_pbs_add_list_entry: handle:%s, name:%s",
+ p_cb->vlist.handle, p_cb->vlist.name);
+
+ sprintf(p_buf, " <" BTA_PBS_CARD_ELEM " = \"%s\" " BTA_PBS_NAME_ATTR " = \"",p_cb->vlist.handle);
+ /* Need to translate special characters to XML format */
+ bta_pbs_translate_special_character(strlen(p_buf) + p_buf, p_cb->vlist.name);
+ sprintf(strlen(p_buf)+p_buf, "\"/>" BTA_PBS_XML_EOL);
+ /* Make sure the entry fits into the current obx packet */
+ size = strlen(p_buf);
+ if (size <= p_obx->bytes_left)
+ {
+ if (size > 0)
+ {
+ memcpy (&p_obx->p_start[p_obx->offset], p_buf, size);
+ p_obx->offset += size;
+ p_obx->bytes_left -= size;
+ }
+ rsp_code = OBX_RSP_OK;
+ }
+ else /* entry did not fit in current obx packet; try to add entry in next obx req */
+ rsp_code = OBX_RSP_CONTINUE;
+
+ /* Done with temporary buffer */
+ GKI_freebuf(p_buf);
+ }
+ else
+ rsp_code = OBX_RSP_SERVICE_UNAVL;
+
+ return (rsp_code);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_clean_getput
+**
+** Description Cleans up the get resources and control block
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pbs_clean_getput(tBTA_PBS_CB *p_cb, BOOLEAN is_aborted)
+{
+ tBTA_PBS_OBJECT objdata;
+
+ /* Clean up control block */
+ utl_freebuf((void**)&p_cb->obx.p_pkt);
+
+ /* Close any open files */
+ if (p_cb->fd >= 0)
+ {
+ bta_pbs_co_close(p_cb->fd);
+ p_cb->fd = BTA_FS_INVALID_FD;
+ }
+
+ /* Notify the application */
+ objdata.p_name = p_cb->p_path;
+
+ if (is_aborted)
+ objdata.status = BTA_PBS_FAIL;
+ else
+ objdata.status = BTA_PBS_OK;
+
+ if (p_cb->p_cback && p_cb->obx_oper != 0)
+ {
+ objdata.operation = p_cb->obx_oper;
+ /* Notify application of operation complete */
+ p_cb->p_cback(BTA_PBS_OPER_CMPL_EVT, (tBTA_PBS *)&objdata);
+ }
+
+ utl_freebuf((void**)&p_cb->p_name);
+ utl_freebuf((void**)&p_cb->p_path);
+
+ p_cb->obx_oper = BTA_PBS_OPER_NONE;
+ p_cb->obj_type = BTA_PBS_NONE_OBJ;
+ p_cb->obx.bytes_left = 0;
+ p_cb->file_length = BTA_FS_LEN_UNKNOWN;
+ p_cb->acc_active = 0;
+// btla-specific ++
+ p_cb->aborting = FALSE;
+// btla-specific --
+ memset(&p_cb->getvlist_app_params, 0, sizeof(p_cb->getvlist_app_params));
+ memset(&p_cb->pullpb_app_params, 0, sizeof(p_cb->pullpb_app_params));
+ memset(&p_cb->vlist, 0, sizeof(p_cb->vlist));
+}
+
+/*****************************************************************************
+* Function: bta_pbs_read_app_params
+* Purpose: Read the application parameters from the given OBX packet
+*****************************************************************************/
+UINT8 * bta_pbs_read_app_params(BT_HDR *p_pkt, UINT8 tag, UINT16 *param_len)
+{
+ UINT8 *p_data = NULL, *p = NULL;
+ UINT16 data_len = 0;
+ int left, len;
+
+ if(OBX_ReadByteStrHdr(p_pkt, OBX_HI_APP_PARMS, &p_data, &data_len, 0))
+ {
+ left = data_len;
+ while(left > 0)
+ {
+ len = *(p_data + 1);
+ if(*p_data == tag)
+ {
+ p_data += 2;
+ p = p_data;
+ *param_len = (UINT16) len;
+ break;
+ }
+ p_data += (len+2);
+ left -= (len+2);
+ }
+ }
+ return p;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_pbs_handle_special_character
+**
+** Description Translate special characters to XML format
+**
+**
+** Returns Void
+**
+*******************************************************************************/
+static void bta_pbs_translate_special_character(char *buffer, const char *str)
+{
+ char *buf=buffer;
+ int slen = strlen(str);
+ int i;
+ for (i=0; i < slen;i++)
+ {
+
+ char c = str[i];
+ switch (c)
+ {
+ case '<':
+ BCM_STRCPY_S(buf,4,"&lt;");
+ buf+=4;
+ break;
+ case '>':
+ BCM_STRCPY_S(buf,4,"&gt;");
+ buf+=4;
+ break;
+ case '\"':
+ BCM_STRCPY_S(buf,6,"&quot;");
+ buf+=6;
+ break;
+ case '\'':
+ BCM_STRCPY_S(buf,6,"&apos;");
+ buf+=6;
+ break;
+ case '&':
+ BCM_STRCPY_S(buf,5,"&amp;");
+ buf+=5;
+ break;
+ default:
+ buf[0]=c;
+ buf++;
+ }
+ }
+ buf[0]='\0';
+
+}
+
+
+
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/sys/bd.c b/bta/sys/bd.c
new file mode 100644
index 0000000..3c639d1
--- /dev/null
+++ b/bta/sys/bd.c
@@ -0,0 +1,99 @@
+/*****************************************************************************
+**
+** Name: bd.c
+**
+** Description: BD address services.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..32cb69a
--- /dev/null
+++ b/bta/sys/bta_sys.h
@@ -0,0 +1,296 @@
+/*****************************************************************************
+**
+** Name: bta_sys.h
+**
+** Description: This is the public interface file for the BTA system
+** manager.
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..4d102ef
--- /dev/null
+++ b/bta/sys/bta_sys_cfg.c
@@ -0,0 +1,42 @@
+/*****************************************************************************
+**
+** Name: bta_sys_cfg.c
+**
+** Description: This file contains compile-time configurable constants
+** for the BTA system manager.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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 */
+ BT_TRACE_LEVEL_DEBUG //TODO: Fix this - 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..d8ef532
--- /dev/null
+++ b/bta/sys/bta_sys_ci.c
@@ -0,0 +1,65 @@
+/*****************************************************************************
+**
+** Name: bta_sys_ci.c
+**
+** Description: This is the implementation file for BTA system call-in
+** functions.
+**
+** Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..63e9fc6
--- /dev/null
+++ b/bta/sys/bta_sys_conn.c
@@ -0,0 +1,565 @@
+/*****************************************************************************
+**
+** Name: bta_sys_conn.c
+**
+** Description: Routes connection status callbacks from various sub systems
+** to DM
+**
+** Copyright (c) 2003-2011, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..ac54453
--- /dev/null
+++ b/bta/sys/bta_sys_int.h
@@ -0,0 +1,107 @@
+/*****************************************************************************
+**
+** Name: bta_sys_int.h
+**
+** Description: This is the private interface file for the BTA system
+** manager.
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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..2b54289
--- /dev/null
+++ b/bta/sys/bta_sys_main.c
@@ -0,0 +1,728 @@
+/*****************************************************************************
+**
+** Name: bta_sys_main.c
+**
+** Description: This is the main implementation file for the BTA
+** system manager.
+**
+** Copyright (c) 2003-2010, Broadcom Corp., All Rights Reserved.
+** Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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;
+
+ 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:
+ BTA_DisableBluetooth();
+ break;
+ default:
+ /* not yet supported */
+ break;
+ }
+ }
+
+ /* turn everything OFF, then re-start the modules that were ON. Let the state machine handle all this... */
+
+ 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:
+ BTA_EnableBluetooth(NULL);
+ 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..24ed246
--- /dev/null
+++ b/bta/sys/ptim.c
@@ -0,0 +1,149 @@
+/*****************************************************************************
+**
+** Name: ptim.c
+**
+** Description: Protocol timer services.
+**
+** Copyright (c) 2003-2006, Broadcom Corp., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#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..1487f2e
--- /dev/null
+++ b/bta/sys/utl.c
@@ -0,0 +1,283 @@
+/*****************************************************************************
+**
+** Name: utl.c
+**
+** Description: This file contains utility functions.
+**
+** Copyright (c) 2003, Widcomm Inc., All Rights Reserved.
+** Widcomm Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+#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;
+}
+
+