From e448862a47c08eb23185aaed574b39264f5005fc Mon Sep 17 00:00:00 2001 From: Andre Eisenbach Date: Wed, 22 Feb 2012 13:18:21 -0800 Subject: Initial Bluedroid stack commit --- bta/Android.mk | 140 ++ bta/ag/bta_ag_act.c | 848 ++++++++ bta/ag/bta_ag_api.c | 310 +++ bta/ag/bta_ag_at.c | 230 +++ bta/ag/bta_ag_at.h | 108 + bta/ag/bta_ag_cfg.c | 51 + bta/ag/bta_ag_ci.c | 86 + bta/ag/bta_ag_cmd.c | 1789 +++++++++++++++++ bta/ag/bta_ag_int.h | 407 ++++ bta/ag/bta_ag_main.c | 1000 ++++++++++ bta/ag/bta_ag_rfc.c | 428 ++++ bta/ag/bta_ag_sco.c | 1650 ++++++++++++++++ bta/ag/bta_ag_sdp.c | 491 +++++ bta/av/bta_av_aact.c | 2688 +++++++++++++++++++++++++ bta/av/bta_av_act.c | 2000 +++++++++++++++++++ bta/av/bta_av_api.c | 568 ++++++ bta/av/bta_av_cfg.c | 276 +++ bta/av/bta_av_ci.c | 85 + bta/av/bta_av_int.h | 706 +++++++ bta/av/bta_av_main.c | 1318 +++++++++++++ bta/av/bta_av_ssm.c | 587 ++++++ bta/dg/bta_dg_act.c | 900 +++++++++ bta/dg/bta_dg_api.c | 218 +++ bta/dg/bta_dg_cfg.c | 54 + bta/dg/bta_dg_ci.c | 159 ++ bta/dg/bta_dg_int.h | 220 +++ bta/dg/bta_dg_main.c | 597 ++++++ bta/dm/bta_dm_act.c | 4678 ++++++++++++++++++++++++++++++++++++++++++++ bta/dm/bta_dm_api.c | 1602 +++++++++++++++ bta/dm/bta_dm_cfg.c | 424 ++++ bta/dm/bta_dm_ci.c | 106 + bta/dm/bta_dm_int.h | 956 +++++++++ bta/dm/bta_dm_main.c | 331 ++++ bta/dm/bta_dm_pm.c | 980 ++++++++++ bta/dm/bta_dm_sco.c | 684 +++++++ bta/fs/bta_fs_cfg.c | 38 + bta/fs/bta_fs_ci.c | 268 +++ bta/ft/bta_ft_cfg.c | 86 + bta/ft/bta_ftc_act.c | 2062 +++++++++++++++++++ bta/ft/bta_ftc_api.c | 796 ++++++++ bta/ft/bta_ftc_int.h | 504 +++++ bta/ft/bta_ftc_main.c | 689 +++++++ bta/ft/bta_ftc_utils.c | 608 ++++++ bta/ft/bta_fts_act.c | 1523 ++++++++++++++ bta/ft/bta_fts_api.c | 230 +++ bta/ft/bta_fts_int.h | 287 +++ bta/ft/bta_fts_main.c | 603 ++++++ bta/ft/bta_fts_sdp.c | 66 + bta/ft/bta_fts_utils.c | 972 +++++++++ bta/gatt/bta_gattc_act.c | 1789 +++++++++++++++++ bta/gatt/bta_gattc_api.c | 922 +++++++++ bta/gatt/bta_gattc_cache.c | 1584 +++++++++++++++ bta/gatt/bta_gattc_ci.c | 125 ++ bta/gatt/bta_gattc_int.h | 452 +++++ bta/gatt/bta_gattc_main.c | 474 +++++ bta/gatt/bta_gattc_utils.c | 652 ++++++ bta/gatt/bta_gatts_act.c | 785 ++++++++ bta/gatt/bta_gatts_api.c | 500 +++++ bta/gatt/bta_gatts_int.h | 233 +++ bta/gatt/bta_gatts_main.c | 122 ++ bta/gatt/bta_gatts_utils.c | 223 +++ bta/hd/bta_hd_act.c | 646 ++++++ bta/hd/bta_hd_api.c | 236 +++ bta/hd/bta_hd_cfg.c | 151 ++ bta/hd/bta_hd_int.h | 166 ++ bta/hd/bta_hd_main.c | 242 +++ bta/hh/bta_hh_act.c | 1160 +++++++++++ bta/hh/bta_hh_api.c | 412 ++++ bta/hh/bta_hh_cfg.c | 52 + bta/hh/bta_hh_int.h | 235 +++ bta/hh/bta_hh_main.c | 429 ++++ bta/hh/bta_hh_utils.c | 409 ++++ bta/hl/bta_hl_act.c | 2794 ++++++++++++++++++++++++++ bta/hl/bta_hl_api.c | 472 +++++ bta/hl/bta_hl_ci.c | 158 ++ bta/hl/bta_hl_int.h | 845 ++++++++ bta/hl/bta_hl_main.c | 1907 ++++++++++++++++++ bta/hl/bta_hl_sdp.c | 429 ++++ bta/hl/bta_hl_utils.c | 3324 +++++++++++++++++++++++++++++++ bta/include/bd.h | 89 + bta/include/bta_ag_api.h | 496 +++++ bta/include/bta_ag_ci.h | 70 + bta/include/bta_ag_co.h | 100 + bta/include/bta_api.h | 1712 ++++++++++++++++ bta/include/bta_av_api.h | 753 +++++++ bta/include/bta_av_ci.h | 62 + bta/include/bta_av_co.h | 400 ++++ bta/include/bta_dg_api.h | 198 ++ bta/include/bta_dg_ci.h | 107 + bta/include/bta_dg_co.h | 198 ++ bta/include/bta_dm_ci.h | 69 + bta/include/bta_dm_co.h | 262 +++ bta/include/bta_fs_api.h | 32 + bta/include/bta_fs_ci.h | 244 +++ bta/include/bta_fs_co.h | 690 +++++++ bta/include/bta_ft_api.h | 724 +++++++ bta/include/bta_gatt_api.h | 1206 ++++++++++++ bta/include/bta_gattc_ci.h | 108 + bta/include/bta_gattc_co.h | 89 + bta/include/bta_gatts_co.h | 70 + bta/include/bta_hd_api.h | 289 +++ bta/include/bta_hh_api.h | 444 +++++ bta/include/bta_hh_co.h | 60 + bta/include/bta_hl_api.h | 895 +++++++++ bta/include/bta_hl_ci.h | 112 ++ bta/include/bta_hl_co.h | 219 +++ bta/include/bta_ma_api.h | 691 +++++++ bta/include/bta_ma_co.h | 91 + bta/include/bta_ma_def.h | 479 +++++ bta/include/bta_mse_api.h | 470 +++++ bta/include/bta_mse_ci.h | 146 ++ bta/include/bta_mse_co.h | 330 ++++ bta/include/bta_op_api.h | 621 ++++++ bta/include/bta_pan_api.h | 187 ++ bta/include/bta_pan_ci.h | 139 ++ bta/include/bta_pan_co.h | 189 ++ bta/include/bta_pbs_api.h | 298 +++ bta/include/bta_pbs_ci.h | 93 + bta/include/bta_pbs_co.h | 160 ++ bta/include/bta_prm_api.h | 57 + bta/include/bta_sc_api.h | 193 ++ bta/include/bta_sc_ci.h | 111 ++ bta/include/bta_sc_co.h | 153 ++ bta/include/bta_sys_ci.h | 57 + bta/include/bta_sys_co.h | 47 + bta/include/ptim.h | 86 + bta/include/utl.h | 156 ++ bta/ma/bta_ma_api.c | 1203 ++++++++++++ bta/ma/bta_ma_util.c | 1750 +++++++++++++++++ bta/ma/bta_ma_util.h | 93 + bta/ma/bta_mse_act.c | 2763 ++++++++++++++++++++++++++ bta/ma/bta_mse_api.c | 437 +++++ bta/ma/bta_mse_cfg.c | 31 + bta/ma/bta_mse_ci.c | 251 +++ bta/ma/bta_mse_int.h | 835 ++++++++ bta/ma/bta_mse_main.c | 1367 +++++++++++++ bta/ma/bta_mse_sdp.c | 63 + bta/ma/bta_mse_utils.c | 3867 ++++++++++++++++++++++++++++++++++++ bta/op/bta_op_fmt.c | 804 ++++++++ bta/op/bta_op_fmt.h | 92 + bta/op/bta_op_vcal.c | 158 ++ bta/op/bta_op_vcard.c | 310 +++ bta/op/bta_op_vnote.c | 99 + bta/op/bta_opc_act.c | 1017 ++++++++++ bta/op/bta_opc_api.c | 214 ++ bta/op/bta_opc_int.h | 257 +++ bta/op/bta_opc_main.c | 425 ++++ bta/op/bta_opc_utils.c | 322 +++ bta/op/bta_ops_act.c | 793 ++++++++ bta/op/bta_ops_api.c | 153 ++ bta/op/bta_ops_int.h | 198 ++ bta/op/bta_ops_main.c | 412 ++++ bta/op/bta_ops_utils.c | 487 +++++ bta/pan/bta_pan_act.c | 718 +++++++ bta/pan/bta_pan_api.c | 202 ++ bta/pan/bta_pan_ci.c | 248 +++ bta/pan/bta_pan_int.h | 200 ++ bta/pan/bta_pan_main.c | 409 ++++ bta/pb/bta_pbs_act.c | 1134 +++++++++++ bta/pb/bta_pbs_api.c | 222 +++ bta/pb/bta_pbs_cfg.c | 38 + bta/pb/bta_pbs_ci.c | 119 ++ bta/pb/bta_pbs_int.h | 305 +++ bta/pb/bta_pbs_main.c | 515 +++++ bta/pb/bta_pbs_sdp.c | 113 ++ bta/pb/bta_pbs_utils.c | 734 +++++++ bta/sys/bd.c | 99 + bta/sys/bta_sys.h | 296 +++ bta/sys/bta_sys_cfg.c | 42 + bta/sys/bta_sys_ci.c | 65 + bta/sys/bta_sys_conn.c | 565 ++++++ bta/sys/bta_sys_int.h | 107 + bta/sys/bta_sys_main.c | 728 +++++++ bta/sys/ptim.c | 149 ++ bta/sys/utl.c | 283 +++ 175 files changed, 98479 insertions(+) create mode 100644 bta/Android.mk create mode 100644 bta/ag/bta_ag_act.c create mode 100644 bta/ag/bta_ag_api.c create mode 100644 bta/ag/bta_ag_at.c create mode 100644 bta/ag/bta_ag_at.h create mode 100644 bta/ag/bta_ag_cfg.c create mode 100644 bta/ag/bta_ag_ci.c create mode 100644 bta/ag/bta_ag_cmd.c create mode 100644 bta/ag/bta_ag_int.h create mode 100644 bta/ag/bta_ag_main.c create mode 100644 bta/ag/bta_ag_rfc.c create mode 100644 bta/ag/bta_ag_sco.c create mode 100644 bta/ag/bta_ag_sdp.c create mode 100644 bta/av/bta_av_aact.c create mode 100644 bta/av/bta_av_act.c create mode 100644 bta/av/bta_av_api.c create mode 100644 bta/av/bta_av_cfg.c create mode 100644 bta/av/bta_av_ci.c create mode 100644 bta/av/bta_av_int.h create mode 100644 bta/av/bta_av_main.c create mode 100644 bta/av/bta_av_ssm.c create mode 100644 bta/dg/bta_dg_act.c create mode 100644 bta/dg/bta_dg_api.c create mode 100644 bta/dg/bta_dg_cfg.c create mode 100644 bta/dg/bta_dg_ci.c create mode 100644 bta/dg/bta_dg_int.h create mode 100644 bta/dg/bta_dg_main.c create mode 100644 bta/dm/bta_dm_act.c create mode 100644 bta/dm/bta_dm_api.c create mode 100644 bta/dm/bta_dm_cfg.c create mode 100644 bta/dm/bta_dm_ci.c create mode 100644 bta/dm/bta_dm_int.h create mode 100644 bta/dm/bta_dm_main.c create mode 100644 bta/dm/bta_dm_pm.c create mode 100644 bta/dm/bta_dm_sco.c create mode 100644 bta/fs/bta_fs_cfg.c create mode 100644 bta/fs/bta_fs_ci.c create mode 100644 bta/ft/bta_ft_cfg.c create mode 100644 bta/ft/bta_ftc_act.c create mode 100644 bta/ft/bta_ftc_api.c create mode 100644 bta/ft/bta_ftc_int.h create mode 100644 bta/ft/bta_ftc_main.c create mode 100644 bta/ft/bta_ftc_utils.c create mode 100644 bta/ft/bta_fts_act.c create mode 100644 bta/ft/bta_fts_api.c create mode 100644 bta/ft/bta_fts_int.h create mode 100644 bta/ft/bta_fts_main.c create mode 100644 bta/ft/bta_fts_sdp.c create mode 100644 bta/ft/bta_fts_utils.c create mode 100644 bta/gatt/bta_gattc_act.c create mode 100644 bta/gatt/bta_gattc_api.c create mode 100644 bta/gatt/bta_gattc_cache.c create mode 100644 bta/gatt/bta_gattc_ci.c create mode 100644 bta/gatt/bta_gattc_int.h create mode 100644 bta/gatt/bta_gattc_main.c create mode 100644 bta/gatt/bta_gattc_utils.c create mode 100644 bta/gatt/bta_gatts_act.c create mode 100644 bta/gatt/bta_gatts_api.c create mode 100644 bta/gatt/bta_gatts_int.h create mode 100644 bta/gatt/bta_gatts_main.c create mode 100644 bta/gatt/bta_gatts_utils.c create mode 100644 bta/hd/bta_hd_act.c create mode 100644 bta/hd/bta_hd_api.c create mode 100644 bta/hd/bta_hd_cfg.c create mode 100644 bta/hd/bta_hd_int.h create mode 100644 bta/hd/bta_hd_main.c create mode 100644 bta/hh/bta_hh_act.c create mode 100644 bta/hh/bta_hh_api.c create mode 100644 bta/hh/bta_hh_cfg.c create mode 100644 bta/hh/bta_hh_int.h create mode 100644 bta/hh/bta_hh_main.c create mode 100644 bta/hh/bta_hh_utils.c create mode 100644 bta/hl/bta_hl_act.c create mode 100644 bta/hl/bta_hl_api.c create mode 100644 bta/hl/bta_hl_ci.c create mode 100644 bta/hl/bta_hl_int.h create mode 100644 bta/hl/bta_hl_main.c create mode 100644 bta/hl/bta_hl_sdp.c create mode 100644 bta/hl/bta_hl_utils.c create mode 100644 bta/include/bd.h create mode 100644 bta/include/bta_ag_api.h create mode 100644 bta/include/bta_ag_ci.h create mode 100644 bta/include/bta_ag_co.h create mode 100644 bta/include/bta_api.h create mode 100644 bta/include/bta_av_api.h create mode 100644 bta/include/bta_av_ci.h create mode 100644 bta/include/bta_av_co.h create mode 100644 bta/include/bta_dg_api.h create mode 100644 bta/include/bta_dg_ci.h create mode 100644 bta/include/bta_dg_co.h create mode 100644 bta/include/bta_dm_ci.h create mode 100644 bta/include/bta_dm_co.h create mode 100644 bta/include/bta_fs_api.h create mode 100644 bta/include/bta_fs_ci.h create mode 100644 bta/include/bta_fs_co.h create mode 100644 bta/include/bta_ft_api.h create mode 100644 bta/include/bta_gatt_api.h create mode 100644 bta/include/bta_gattc_ci.h create mode 100644 bta/include/bta_gattc_co.h create mode 100644 bta/include/bta_gatts_co.h create mode 100644 bta/include/bta_hd_api.h create mode 100644 bta/include/bta_hh_api.h create mode 100644 bta/include/bta_hh_co.h create mode 100644 bta/include/bta_hl_api.h create mode 100644 bta/include/bta_hl_ci.h create mode 100644 bta/include/bta_hl_co.h create mode 100644 bta/include/bta_ma_api.h create mode 100644 bta/include/bta_ma_co.h create mode 100644 bta/include/bta_ma_def.h create mode 100644 bta/include/bta_mse_api.h create mode 100644 bta/include/bta_mse_ci.h create mode 100644 bta/include/bta_mse_co.h create mode 100644 bta/include/bta_op_api.h create mode 100644 bta/include/bta_pan_api.h create mode 100644 bta/include/bta_pan_ci.h create mode 100644 bta/include/bta_pan_co.h create mode 100644 bta/include/bta_pbs_api.h create mode 100644 bta/include/bta_pbs_ci.h create mode 100644 bta/include/bta_pbs_co.h create mode 100644 bta/include/bta_prm_api.h create mode 100644 bta/include/bta_sc_api.h create mode 100644 bta/include/bta_sc_ci.h create mode 100644 bta/include/bta_sc_co.h create mode 100644 bta/include/bta_sys_ci.h create mode 100644 bta/include/bta_sys_co.h create mode 100644 bta/include/ptim.h create mode 100644 bta/include/utl.h create mode 100644 bta/ma/bta_ma_api.c create mode 100644 bta/ma/bta_ma_util.c create mode 100644 bta/ma/bta_ma_util.h create mode 100644 bta/ma/bta_mse_act.c create mode 100644 bta/ma/bta_mse_api.c create mode 100644 bta/ma/bta_mse_cfg.c create mode 100644 bta/ma/bta_mse_ci.c create mode 100644 bta/ma/bta_mse_int.h create mode 100644 bta/ma/bta_mse_main.c create mode 100644 bta/ma/bta_mse_sdp.c create mode 100644 bta/ma/bta_mse_utils.c create mode 100644 bta/op/bta_op_fmt.c create mode 100644 bta/op/bta_op_fmt.h create mode 100644 bta/op/bta_op_vcal.c create mode 100644 bta/op/bta_op_vcard.c create mode 100644 bta/op/bta_op_vnote.c create mode 100644 bta/op/bta_opc_act.c create mode 100644 bta/op/bta_opc_api.c create mode 100644 bta/op/bta_opc_int.h create mode 100644 bta/op/bta_opc_main.c create mode 100644 bta/op/bta_opc_utils.c create mode 100644 bta/op/bta_ops_act.c create mode 100644 bta/op/bta_ops_api.c create mode 100644 bta/op/bta_ops_int.h create mode 100644 bta/op/bta_ops_main.c create mode 100644 bta/op/bta_ops_utils.c create mode 100644 bta/pan/bta_pan_act.c create mode 100644 bta/pan/bta_pan_api.c create mode 100644 bta/pan/bta_pan_ci.c create mode 100644 bta/pan/bta_pan_int.h create mode 100644 bta/pan/bta_pan_main.c create mode 100644 bta/pb/bta_pbs_act.c create mode 100644 bta/pb/bta_pbs_api.c create mode 100644 bta/pb/bta_pbs_cfg.c create mode 100644 bta/pb/bta_pbs_ci.c create mode 100644 bta/pb/bta_pbs_int.h create mode 100644 bta/pb/bta_pbs_main.c create mode 100644 bta/pb/bta_pbs_sdp.c create mode 100644 bta/pb/bta_pbs_utils.c create mode 100644 bta/sys/bd.c create mode 100644 bta/sys/bta_sys.h create mode 100644 bta/sys/bta_sys_cfg.c create mode 100644 bta/sys/bta_sys_ci.c create mode 100644 bta/sys/bta_sys_conn.c create mode 100644 bta/sys/bta_sys_int.h create mode 100644 bta/sys/bta_sys_main.c create mode 100644 bta/sys/ptim.c create mode 100644 bta/sys/utl.c (limited to 'bta') 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 + +/***************************************************************************** +** Constants +*****************************************************************************/ + +/* maximum length of data to read from RFCOMM */ +#define BTA_AG_RFC_READ_MAX 512 + +/* maximum AT command length */ +#define BTA_AG_CMD_MAX 512 + +const UINT16 bta_ag_uuid[BTA_AG_NUM_IDX] = +{ + UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY, + UUID_SERVCLASS_AG_HANDSFREE +}; + +const UINT8 bta_ag_sec_id[BTA_AG_NUM_IDX] = +{ + BTM_SEC_SERVICE_HEADSET_AG, + BTM_SEC_SERVICE_AG_HANDSFREE +}; + +const tBTA_SERVICE_ID bta_ag_svc_id[BTA_AG_NUM_IDX] = +{ + BTA_HSP_SERVICE_ID, + BTA_HFP_SERVICE_ID +}; + +const tBTA_SERVICE_MASK bta_ag_svc_mask[BTA_AG_NUM_IDX] = +{ + BTA_HSP_SERVICE_MASK, + BTA_HFP_SERVICE_MASK +}; + +typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, + char *p_arg, INT16 int_arg); + +const tBTA_AG_ATCMD_CBACK bta_ag_at_cback_tbl[BTA_AG_NUM_IDX] = +{ + bta_ag_at_hsp_cback, + bta_ag_at_hfp_cback +}; + +/******************************************************************************* +** +** Function bta_ag_cback_open +** +** Description Send open callback event to application. +** +** +** Returns void +** +*******************************************************************************/ +static void bta_ag_cback_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data, tBTA_AG_STATUS status) +{ + tBTA_AG_OPEN open; + + /* call app callback with open event */ + open.hdr.handle = bta_ag_scb_to_idx(p_scb); + open.hdr.app_id = p_scb->app_id; + open.status = status; + open.service_id = bta_ag_svc_id[p_scb->conn_service]; + if(p_data) + { + /* if p_data is provided then we need to pick the bd address from the open api structure */ + bdcpy(open.bd_addr, p_data->api_open.bd_addr); + } + else + { + bdcpy(open.bd_addr, p_scb->peer_addr); + } + + (*bta_ag_cb.p_cback)(BTA_AG_OPEN_EVT, (tBTA_AG *) &open); +} + +/******************************************************************************* +** +** Function bta_ag_register +** +** Description This function initializes values of the AG cb and sets up +** the SDP record for the services. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_register(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + tBTA_AG_REGISTER reg; + + /* initialize control block */ + p_scb->reg_services = p_data->api_register.services; + p_scb->serv_sec_mask = p_data->api_register.sec_mask; + p_scb->features = p_data->api_register.features; + p_scb->app_id = p_data->api_register.app_id; + + /* create SDP records */ + bta_ag_create_records(p_scb, p_data); + + /* start RFCOMM servers */ + bta_ag_start_servers(p_scb, p_scb->reg_services); + + /* call app callback with register event */ + reg.hdr.handle = bta_ag_scb_to_idx(p_scb); + reg.hdr.app_id = p_scb->app_id; + reg.status = BTA_AG_SUCCESS; + (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG *) ®); +} + +/******************************************************************************* +** +** Function bta_ag_deregister +** +** Description This function removes the sdp records, closes the RFCOMM +** servers, and deallocates the service control block. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_deregister(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* set dealloc */ + p_scb->dealloc = TRUE; + + /* remove sdp records */ + bta_ag_del_records(p_scb, p_data); + + /* remove rfcomm servers */ + bta_ag_close_servers(p_scb, p_scb->reg_services); + + /* dealloc */ + bta_ag_scb_dealloc(p_scb); +} + +/******************************************************************************* +** +** Function bta_ag_start_dereg +** +** Description Start a deregister event. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_start_dereg(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* set dealloc */ + p_scb->dealloc = TRUE; + + /* remove sdp records */ + bta_ag_del_records(p_scb, p_data); +} + +/******************************************************************************* +** +** Function bta_ag_start_open +** +** Description This starts an AG open. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + BD_ADDR pending_bd_addr; + + /* store parameters */ + if (p_data) + { + bdcpy(p_scb->peer_addr, p_data->api_open.bd_addr); + p_scb->open_services = p_data->api_open.services; + p_scb->cli_sec_mask = p_data->api_open.sec_mask; + } + + /* Check if RFCOMM has any incoming connection to avoid collision. */ + if (PORT_IsOpening (pending_bd_addr)) + { + /* Let the incoming connection goes through. */ + /* Issue collision for this scb for now. */ + /* We will decide what to do when we find incoming connetion later. */ + bta_ag_collision_cback (0, BTA_ID_AG, 0, p_scb->peer_addr); + return; + } + + /* close servers */ + bta_ag_close_servers(p_scb, p_scb->reg_services); + + /* set role */ + p_scb->role = BTA_AG_INT; + + /* do service search */ + bta_ag_do_disc(p_scb, p_scb->open_services); +} + +/******************************************************************************* +** +** Function bta_ag_disc_int_res +** +** Description This function handles a discovery result when initiator. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_disc_int_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + UINT16 event = BTA_AG_DISC_FAIL_EVT; + + APPL_TRACE_DEBUG1 ("bta_ag_disc_int_res: Status: %d", p_data->disc_result.status); + + /* if found service */ + if (p_data->disc_result.status == SDP_SUCCESS || + p_data->disc_result.status == SDP_DB_FULL) + { + /* get attributes */ + if (bta_ag_sdp_find_attr(p_scb, p_scb->open_services)) + { + /* set connected service */ + p_scb->conn_service = bta_ag_service_to_idx(p_scb->open_services); + + /* send ourselves sdp ok event */ + event = BTA_AG_DISC_OK_EVT; + } + } + + /* free discovery db */ + bta_ag_free_db(p_scb, p_data); + + /* if service not found check if we should search for other service */ + if ((event == BTA_AG_DISC_FAIL_EVT) && + (p_data->disc_result.status == SDP_SUCCESS || + p_data->disc_result.status == SDP_DB_FULL || + p_data->disc_result.status == SDP_NO_RECS_MATCH)) + { + if ((p_scb->open_services & BTA_HFP_SERVICE_MASK) && + (p_scb->open_services & BTA_HSP_SERVICE_MASK)) + { + /* search for HSP */ + p_scb->open_services &= ~BTA_HFP_SERVICE_MASK; + bta_ag_do_disc(p_scb, p_scb->open_services); + } + else if ((p_scb->open_services & BTA_HSP_SERVICE_MASK) && + (p_scb->hsp_version == HSP_VERSION_1_2)) + { + /* search for UUID_SERVCLASS_HEADSET for HSP 1.0 device */ + p_scb->hsp_version = HSP_VERSION_1_0; + bta_ag_do_disc(p_scb, p_scb->open_services); + } + else + { + /* send ourselves sdp ok/fail event */ + bta_ag_sm_execute(p_scb, event, p_data); + } + } + else + { + /* send ourselves sdp ok/fail event */ + bta_ag_sm_execute(p_scb, event, p_data); + } + +} + +/******************************************************************************* +** +** Function bta_ag_disc_acp_res +** +** Description This function handles a discovery result when acceptor. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_disc_acp_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* if found service */ + if (p_data->disc_result.status == SDP_SUCCESS || + p_data->disc_result.status == SDP_DB_FULL) + { + /* get attributes */ + bta_ag_sdp_find_attr(p_scb, bta_ag_svc_mask[p_scb->conn_service]); + } + + /* free discovery db */ + bta_ag_free_db(p_scb, p_data); +} + +/******************************************************************************* +** +** Function bta_ag_disc_fail +** +** Description This function handles a discovery failure. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_disc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* reopen registered servers */ + bta_ag_start_servers(p_scb, p_scb->reg_services); + + /* reinitialize stuff */ + + /* call open cback w. failure */ + bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP); +} + +/******************************************************************************* +** +** Function bta_ag_open_fail +** +** Description open connection failed. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_open_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* call open cback w. failure */ + bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES); +} + +/******************************************************************************* +** +** Function bta_ag_rfc_fail +** +** Description RFCOMM connection failed. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* reinitialize stuff */ + p_scb->conn_handle = 0; + p_scb->conn_service = 0; + p_scb->peer_features = 0; +#if (BTM_WBS_INCLUDED == TRUE ) + p_scb->peer_codecs = BTA_AG_CODEC_NONE; + p_scb->sco_codec = BTA_AG_CODEC_NONE; +#endif + p_scb->role = 0; + p_scb->svc_conn = FALSE; + p_scb->hsp_version = HSP_VERSION_1_2; + + /* reopen registered servers */ + bta_ag_start_servers(p_scb, p_scb->reg_services); + + /* call open cback w. failure */ + bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM); +} + +/******************************************************************************* +** +** Function bta_ag_rfc_close +** +** Description RFCOMM connection closed. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + tBTA_AG_HDR close; + tBTA_SERVICE_MASK services; + int i, num_active_conn = 0; + +#ifdef _WIN32_WCE + /* The BTE RFCOMM automatically removes the connection when closed, but BTW does not */ + if (p_scb->conn_handle != 0) + RFCOMM_RemoveConnection (p_scb->conn_handle); +#endif + + /* reinitialize stuff */ + p_scb->conn_service = 0; + p_scb->peer_features = 0; +#if (BTM_WBS_INCLUDED == TRUE ) + p_scb->peer_codecs = BTA_AG_CODEC_NONE; + p_scb->sco_codec = BTA_AG_CODEC_NONE; +#endif + p_scb->role = 0; + p_scb->post_sco = BTA_AG_POST_SCO_NONE; + p_scb->svc_conn = FALSE; + p_scb->hsp_version = HSP_VERSION_1_2; + bta_ag_at_reinit(&p_scb->at_cb); + + /* stop timers */ + bta_sys_stop_timer(&p_scb->act_timer); +#if (BTM_WBS_INCLUDED == TRUE) + bta_sys_stop_timer(&p_scb->cn_timer); +#endif + + close.handle = bta_ag_scb_to_idx(p_scb); + close.app_id = p_scb->app_id; + + bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + + /* call close call-out */ + bta_ag_co_data_close(close.handle); + + /* call close cback */ + (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close); + + /* if not deregistering (deallocating) reopen registered servers */ + if (p_scb->dealloc == FALSE) + { + /* Clear peer bd_addr so instance can be reused */ + bdcpy(p_scb->peer_addr, bd_addr_null); + + /* start only unopened server */ + services = p_scb->reg_services; + for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++) + { + if(p_scb->serv_handle[i]) + services &= ~((tBTA_SERVICE_MASK)1 << (BTA_HSP_SERVICE_ID + i)); + } + bta_ag_start_servers(p_scb, services); + + p_scb->conn_handle = 0; + + /* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */ + bta_ag_sco_shutdown(p_scb, NULL); + + /* Check if all the SLCs are down */ + for (i = 0; i < BTA_AG_NUM_SCB; i++) + { + if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn) + num_active_conn++; + } + + if(!num_active_conn) + { + bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + } + + } + /* else close port and deallocate scb */ + else + { + RFCOMM_RemoveServer(p_scb->conn_handle); + bta_ag_scb_dealloc(p_scb); + } +} + +/******************************************************************************* +** +** Function bta_ag_rfc_open +** +** Description Handle RFCOMM channel open. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* initialize AT feature variables */ + p_scb->clip_enabled = FALSE; + p_scb->ccwa_enabled = FALSE; + p_scb->cmer_enabled = FALSE; + p_scb->cmee_enabled = FALSE; + p_scb->inband_enabled = ((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND); + + /* set up AT command interpreter */ + p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD *) bta_ag_at_tbl[p_scb->conn_service]; + p_scb->at_cb.p_cmd_cback = (tBTA_AG_AT_CMD_CBACK *) bta_ag_at_cback_tbl[p_scb->conn_service]; + p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK *) bta_ag_at_err_cback; + p_scb->at_cb.p_user = p_scb; + p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX; + bta_ag_at_init(&p_scb->at_cb); + + /* call app open call-out */ + bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb), bta_ag_svc_id[p_scb->conn_service]); + + bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + + bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS); + + if (p_scb->conn_service == BTA_AG_HFP) + { + /* if hfp start timer for service level conn */ + bta_sys_start_timer(&p_scb->act_timer, BTA_AG_SVC_TOUT_EVT, p_bta_ag_cfg->conn_tout); + } + else + { + /* else service level conn is open */ + bta_ag_svc_conn_open(p_scb, p_data); + } +} + +/******************************************************************************* +** +** Function bta_ag_rfc_acp_open +** +** Description Handle RFCOMM channel open when accepting connection. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + UINT16 lcid; + int i; + tBTA_AG_SCB *ag_scb, *other_scb; + BD_ADDR dev_addr; + int status; + + /* set role */ + p_scb->role = BTA_AG_ACP; + + APPL_TRACE_DEBUG2 ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d", + p_scb->serv_handle[0], p_scb->serv_handle[1]); + + /* get bd addr of peer */ + if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid))) + { + APPL_TRACE_DEBUG1 ("bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d", status); + } + + /* Collision Handling */ + for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++) + { + if ((ag_scb->in_use) && (ag_scb->colli_tmr_on)) + { + /* stop collision timer */ + ag_scb->colli_tmr_on = FALSE; + bta_sys_stop_timer (&ag_scb->colli_timer); + + if (bdcmp (dev_addr, ag_scb->peer_addr) == 0) + { + /* If incoming and outgoing device are same, nothing more to do. */ + /* Outgoing conn will be aborted because we have successful incoming conn. */ + } + else + { + /* Resume outgoing connection. */ + other_scb = bta_ag_get_other_idle_scb (p_scb); + if (other_scb) + { + bdcpy(other_scb->peer_addr, ag_scb->peer_addr); + other_scb->open_services = ag_scb->open_services; + other_scb->cli_sec_mask = ag_scb->cli_sec_mask; + + bta_ag_resume_open (other_scb); + } + } + + break; + } + } + + bdcpy (p_scb->peer_addr, dev_addr); + + /* determine connected service from port handle */ + for (i = 0; i < BTA_AG_NUM_IDX; i++) + { + APPL_TRACE_DEBUG3 ("bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", + i, p_scb->serv_handle[i], p_data->rfc.port_handle); + + if (p_scb->serv_handle[i] == p_data->rfc.port_handle) + { + p_scb->conn_service = i; + p_scb->conn_handle = p_data->rfc.port_handle; + break; + } + } + + APPL_TRACE_DEBUG2 ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d", + p_scb->conn_service, p_scb->conn_handle); + + /* close any unopened server */ + bta_ag_close_servers(p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service])); + + /* do service discovery to get features */ + bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]); + + /* continue with common open processing */ + bta_ag_rfc_open(p_scb, p_data); + + + +} + +/******************************************************************************* +** +** Function bta_ag_rfc_data +** +** Description Read and process data from RFCOMM. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + UINT16 len; + char buf[BTA_AG_RFC_READ_MAX]; + + memset(buf, 0, BTA_AG_RFC_READ_MAX); + + /* do the following */ + for(;;) + { + /* read data from rfcomm; if bad status, we're done */ + if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) != PORT_SUCCESS) + { + break; + } + + /* if no data, we're done */ + if (len == 0) + { + break; + } + + /* run AT command interpreter on data */ + bta_ag_at_parse(&p_scb->at_cb, buf, len); + + /* no more data to read, we're done */ + if (len < BTA_AG_RFC_READ_MAX) + { + break; + } + } +} + +/******************************************************************************* +** +** Function bta_ag_start_close +** +** Description Start the process of closing SCO and RFCOMM connection. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* 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 + +/***************************************************************************** +** 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 +#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 +#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 +#include + +/***************************************************************************** +** 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 +#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 *) ®); + } +} + +/******************************************************************************* +** +** 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 +#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, ¶ms); + /* If ESCO or EDR ESCO, retry with SCO only in case of failure */ + if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK) + ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_AG_NO_EDR_ESCO)) + { +#if (BTM_WBS_INCLUDED == TRUE ) + if (esco_codec != BTA_AG_CODEC_MSBC) + { + p_scb->retry_with_sco_only = TRUE; + APPL_TRACE_API0("Setting retry_with_sco_only to TRUE"); + } + else /* Do not use SCO when using mSBC */ + { + p_scb->retry_with_sco_only = FALSE; + APPL_TRACE_API0("Setting retry_with_sco_only to FALSE"); + } +#else + p_scb->retry_with_sco_only = TRUE; + APPL_TRACE_API0("Setting retry_with_sco_only to TRUE"); +#endif + } + } + else + { + if(p_scb->retry_with_sco_only) + APPL_TRACE_API0("retrying with SCO only"); + p_scb->retry_with_sco_only = FALSE; + + BTM_SetEScoMode(BTM_LINK_TYPE_SCO, ¶ms); + } + + bta_ag_cb.sco.p_curr_scb = p_scb; + + /* tell sys to stop av if any */ + bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + + /* Allow any platform specific pre-SCO set up to take place */ + bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP); + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) + if (esco_codec == BTA_AG_CODEC_MSBC) + pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_16K; + else +#endif + pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K; + + sco_route = bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id); +#endif + +#if (BTM_WBS_INCLUDED == TRUE ) + if (esco_codec == BTA_AG_CODEC_MSBC) + { + /* Enable mSBC codec in fw */ + BTM_SetWBSCodec (esco_codec); + } + + /* Specify PCM input for SBC codec in fw */ + BTM_ConfigI2SPCM (esco_codec, (UINT8)HCI_BRCM_I2SPCM_IS_DEFAULT_ROLE, (UINT8)HCI_BRCM_I2SPCM_SAMPLE_DEFAULT, (UINT8)HCI_BRCM_I2SPCM_CLOCK_DEFAULT); + + /* This setting may not be necessary */ + /* To be verified with stable 2049 boards */ + if (esco_codec == BTA_AG_CODEC_MSBC) + BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS); + else + BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD); + + /* save the current codec because sco_codec can be updated while SCO is open. */ + p_scb->inuse_codec = esco_codec; +#endif + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */ + BTM_ConfigScoPath(sco_route, bta_ag_sco_read_cback, NULL, TRUE); +#endif + bta_ag_cb.sco.cur_idx = p_scb->sco_idx; + } + else + p_scb->retry_with_sco_only = FALSE; + + p_bd_addr = p_scb->peer_addr; + + status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types, + &p_scb->sco_idx, bta_ag_sco_conn_cback, + bta_ag_sco_disc_cback); + if (status == BTM_CMD_STARTED) + { + if (!is_orig) + { + BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback); + } + else /* Initiating the connection, set the current sco handle */ + { + bta_ag_cb.sco.cur_idx = p_scb->sco_idx; + } + } + + APPL_TRACE_API4("ag create sco: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x", + is_orig, p_scb->sco_idx, status, params.packet_types); +} + +#if (BTM_WBS_INCLUDED == TRUE ) +/******************************************************************************* +** +** Function bta_ag_cn_timer_cback +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +static void bta_ag_cn_timer_cback (TIMER_LIST_ENT *p_tle) +{ + tBTA_AG_SCB *p_scb; + + if (p_tle) + { + p_scb = (tBTA_AG_SCB *)p_tle->param; + + if (p_scb) + { + /* Announce that codec negotiation failed. */ + bta_ag_sco_codec_nego(p_scb, FALSE); + + /* call app callback */ + bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT); + } + } +} + +/******************************************************************************* +** +** Function bta_ag_codec_negotiate +** +** Description Initiate codec negotiation by sending AT command. +** If not necessary, skip negotiation. +** +** Returns void +** +*******************************************************************************/ +void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb) +{ + bta_ag_cb.sco.p_curr_scb = p_scb; + + if (p_scb->codec_updated || p_scb->codec_fallback) + { + /* Change the power mode to Active until sco open is completed. */ + bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + + /* Send +BCS to the peer */ + bta_ag_send_bcs(p_scb, NULL); + + /* Start timer to handle timeout */ + p_scb->cn_timer.p_cback = (TIMER_CBACK*)&bta_ag_cn_timer_cback; + p_scb->cn_timer.param = (INT32)p_scb; + bta_sys_start_timer(&p_scb->cn_timer, 0, BTA_AG_CODEC_NEGO_TIMEOUT); + } + else + { + /* use same codec type as previous SCO connection, skip codec negotiation */ + bta_ag_sco_codec_nego(p_scb, TRUE); + } +} +#endif + +/******************************************************************************* +** +** Function bta_ag_sco_event +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event) +{ + tBTA_AG_SCO_CB *p_sco = &bta_ag_cb.sco; +#if (BTM_WBS_INCLUDED == TRUE ) + tBTA_AG_SCB *p_cn_scb = NULL; /* For codec negotiation */ +#endif +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + BT_HDR *p_buf; +#endif +#if BTA_AG_SCO_DEBUG == TRUE + UINT8 in_state = p_sco->state; + + APPL_TRACE_EVENT5("BTA ag sco evt (hdl 0x%04x): State %d (%s), Event %d (%s)", + p_scb->sco_idx, + p_sco->state, bta_ag_sco_state_str(p_sco->state), + event, bta_ag_sco_evt_str(event)); +#else + APPL_TRACE_EVENT3("BTA ag sco evt (hdl 0x%04x): State %d, Event %d", + p_scb->sco_idx, p_sco->state, event); +#endif + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + if (event == BTA_AG_SCO_CI_DATA_E) + { + while (TRUE) + { + bta_dm_sco_co_out_data(&p_buf); + if (p_buf) + { + if (p_sco->state == BTA_AG_SCO_OPEN_ST) + BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf); + else + GKI_freebuf(p_buf); + } + else + break; + } + + return; + } +#endif + + switch (p_sco->state) + { + case BTA_AG_SCO_SHUTDOWN_ST: + switch (event) + { + case BTA_AG_SCO_LISTEN_E: + /* create sco listen connection */ + bta_ag_create_sco(p_scb, FALSE); + p_sco->state = BTA_AG_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_AG_SCO_LISTEN_ST: + switch (event) + { + case BTA_AG_SCO_LISTEN_E: + /* create sco listen connection (Additional channel) */ + bta_ag_create_sco(p_scb, FALSE); + break; + + case BTA_AG_SCO_OPEN_E: + /* remove listening connection */ + bta_ag_remove_sco(p_scb, FALSE); + +#if (BTM_WBS_INCLUDED == TRUE ) + /* start codec negotiation */ + p_sco->state = BTA_AG_SCO_CODEC_ST; + p_cn_scb = p_scb; +#else + /* create sco connection to peer */ + bta_ag_create_sco(p_scb, TRUE); + p_sco->state = BTA_AG_SCO_OPENING_ST; +#endif + break; + + case BTA_AG_SCO_SHUTDOWN_E: + /* remove listening connection */ + bta_ag_remove_sco(p_scb, FALSE); + + if (p_scb == p_sco->p_curr_scb) + p_sco->p_curr_scb = NULL; + + /* If last SCO instance then finish shutting down */ + if (!bta_ag_other_scb_open(p_scb)) + { + p_sco->state = BTA_AG_SCO_SHUTDOWN_ST; + } + break; + + case BTA_AG_SCO_CLOSE_E: + /* remove listening connection */ + /* Ignore the event. We need to keep listening SCO for the active SLC */ + APPL_TRACE_WARNING1("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event); + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* sco failed; create sco listen connection */ + bta_ag_create_sco(p_scb, FALSE); + p_sco->state = BTA_AG_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event); + break; + } + break; + +#if (BTM_WBS_INCLUDED == TRUE ) + case BTA_AG_SCO_CODEC_ST: + switch (event) + { + case BTA_AG_SCO_LISTEN_E: + /* create sco listen connection (Additional channel) */ + bta_ag_create_sco(p_scb, FALSE); + break; + + case BTA_AG_SCO_CN_DONE_E: + /* create sco connection to peer */ + bta_ag_create_sco(p_scb, TRUE); + p_sco->state = BTA_AG_SCO_OPENING_ST; + break; + + case BTA_AG_SCO_XFER_E: + /* save xfer scb */ + p_sco->p_xfer_scb = p_scb; + p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; + break; + + case BTA_AG_SCO_SHUTDOWN_E: + /* remove listening connection */ + bta_ag_remove_sco(p_scb, FALSE); + + if (p_scb == p_sco->p_curr_scb) + p_sco->p_curr_scb = NULL; + + /* If last SCO instance then finish shutting down */ + if (!bta_ag_other_scb_open(p_scb)) + { + p_sco->state = BTA_AG_SCO_SHUTDOWN_ST; + } + break; + + case BTA_AG_SCO_CLOSE_E: + /* sco open is not started yet. just go back to listening */ + p_sco->state = BTA_AG_SCO_LISTEN_ST; + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* sco failed; create sco listen connection */ + bta_ag_create_sco(p_scb, FALSE); + p_sco->state = BTA_AG_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_CODEC_ST: Ignoring event %d", event); + break; + } + break; +#endif + + case BTA_AG_SCO_OPENING_ST: + switch (event) + { + case BTA_AG_SCO_LISTEN_E: + /* second headset has now joined */ + /* create sco listen connection (Additional channel) */ + if (p_scb != p_sco->p_curr_scb) + { + bta_ag_create_sco(p_scb, FALSE); + } + break; + +#if (BTM_WBS_INCLUDED == TRUE) + case BTA_AG_SCO_REOPEN_E: + /* start codec negotiation */ + p_sco->state = BTA_AG_SCO_CODEC_ST; + p_cn_scb = p_scb; + break; +#endif + + case BTA_AG_SCO_XFER_E: + /* save xfer scb */ + p_sco->p_xfer_scb = p_scb; + p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; + break; + + case BTA_AG_SCO_CLOSE_E: + p_sco->state = BTA_AG_SCO_OPEN_CL_ST; + break; + + case BTA_AG_SCO_SHUTDOWN_E: + /* If not opening scb, just close it */ + if (p_scb != p_sco->p_curr_scb) + { + /* remove listening connection */ + bta_ag_remove_sco(p_scb, FALSE); + } + else + p_sco->state = BTA_AG_SCO_SHUTTING_ST; + + break; + + case BTA_AG_SCO_CONN_OPEN_E: + p_sco->state = BTA_AG_SCO_OPEN_ST; + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* sco failed; create sco listen connection */ + bta_ag_create_sco(p_scb, FALSE); + p_sco->state = BTA_AG_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_OPENING_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_AG_SCO_OPEN_CL_ST: + switch (event) + { + case BTA_AG_SCO_XFER_E: + /* save xfer scb */ + p_sco->p_xfer_scb = p_scb; + + p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; + break; + + case BTA_AG_SCO_OPEN_E: + p_sco->state = BTA_AG_SCO_OPENING_ST; + break; + + case BTA_AG_SCO_SHUTDOWN_E: + /* If not opening scb, just close it */ + if (p_scb != p_sco->p_curr_scb) + { + /* remove listening connection */ + bta_ag_remove_sco(p_scb, FALSE); + } + else + p_sco->state = BTA_AG_SCO_SHUTTING_ST; + + break; + + case BTA_AG_SCO_CONN_OPEN_E: + /* close sco connection */ + bta_ag_remove_sco(p_scb, TRUE); + + p_sco->state = BTA_AG_SCO_CLOSING_ST; + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* sco failed; create sco listen connection */ + + p_sco->state = BTA_AG_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_AG_SCO_OPEN_XFER_ST: + switch (event) + { + case BTA_AG_SCO_CLOSE_E: + /* close sco connection */ + bta_ag_remove_sco(p_scb, TRUE); + + p_sco->state = BTA_AG_SCO_CLOSING_ST; + break; + + case BTA_AG_SCO_SHUTDOWN_E: + /* remove all connection */ + bta_ag_remove_sco(p_scb, FALSE); + p_sco->state = BTA_AG_SCO_SHUTTING_ST; + + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* closed sco; place in listen mode and + accept the transferred connection */ + bta_ag_create_sco(p_scb, FALSE); /* Back into listen mode */ + + /* Accept sco connection with xfer scb */ + bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data); + p_sco->state = BTA_AG_SCO_OPENING_ST; + p_sco->p_curr_scb = p_sco->p_xfer_scb; + p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx; + p_sco->p_xfer_scb = NULL; + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_AG_SCO_OPEN_ST: + switch (event) + { + case BTA_AG_SCO_LISTEN_E: + /* second headset has now joined */ + /* create sco listen connection (Additional channel) */ + if (p_scb != p_sco->p_curr_scb) + { + bta_ag_create_sco(p_scb, FALSE); + } + break; + + case BTA_AG_SCO_XFER_E: + /* close current sco connection */ + bta_ag_remove_sco(p_sco->p_curr_scb, TRUE); + + /* save xfer scb */ + p_sco->p_xfer_scb = p_scb; + + p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; + break; + + case BTA_AG_SCO_CLOSE_E: + /* close sco connection if active */ + if (bta_ag_remove_sco(p_scb, TRUE)) + { + p_sco->state = BTA_AG_SCO_CLOSING_ST; + } + break; + + case BTA_AG_SCO_SHUTDOWN_E: + /* remove all listening connections */ + bta_ag_remove_sco(p_scb, FALSE); + + /* If SCO was active on this scb, close it */ + if (p_scb == p_sco->p_curr_scb) + { + p_sco->state = BTA_AG_SCO_SHUTTING_ST; + } + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* peer closed sco; create sco listen connection */ + bta_ag_create_sco(p_scb, FALSE); + p_sco->state = BTA_AG_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_AG_SCO_CLOSING_ST: + switch (event) + { + case BTA_AG_SCO_LISTEN_E: + /* create sco listen connection (Additional channel) */ + if (p_scb != p_sco->p_curr_scb) + { + bta_ag_create_sco(p_scb, FALSE); + } + break; + + case BTA_AG_SCO_OPEN_E: + p_sco->state = BTA_AG_SCO_CLOSE_OP_ST; + break; + + case BTA_AG_SCO_XFER_E: + /* save xfer scb */ + p_sco->p_xfer_scb = p_scb; + + p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST; + break; + + case BTA_AG_SCO_SHUTDOWN_E: + /* If not closing scb, just close it */ + if (p_scb != p_sco->p_curr_scb) + { + /* remove listening connection */ + bta_ag_remove_sco(p_scb, FALSE); + } + else + p_sco->state = BTA_AG_SCO_SHUTTING_ST; + + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* peer closed sco; create sco listen connection */ + bta_ag_create_sco(p_scb, FALSE); + + p_sco->state = BTA_AG_SCO_LISTEN_ST; + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSING_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_AG_SCO_CLOSE_OP_ST: + switch (event) + { + case BTA_AG_SCO_CLOSE_E: + p_sco->state = BTA_AG_SCO_CLOSING_ST; + break; + + case BTA_AG_SCO_SHUTDOWN_E: + p_sco->state = BTA_AG_SCO_SHUTTING_ST; + break; + + case BTA_AG_SCO_CONN_CLOSE_E: +#if (BTM_WBS_INCLUDED == TRUE ) + /* start codec negotiation */ + p_sco->state = BTA_AG_SCO_CODEC_ST; + p_cn_scb = p_scb; +#else + /* open sco connection */ + bta_ag_create_sco(p_scb, TRUE); + p_sco->state = BTA_AG_SCO_OPENING_ST; +#endif + break; + + case BTA_AG_SCO_LISTEN_E: + /* create sco listen connection (Additional channel) */ + if (p_scb != p_sco->p_curr_scb) + { + bta_ag_create_sco(p_scb, FALSE); + } + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_AG_SCO_CLOSE_XFER_ST: + switch (event) + { + case BTA_AG_SCO_CONN_OPEN_E: + /* close sco connection so headset can be transferred + Probably entered this state from "opening state" */ + bta_ag_remove_sco(p_scb, TRUE); + break; + + case BTA_AG_SCO_CLOSE_E: + /* clear xfer scb */ + p_sco->p_xfer_scb = NULL; + + p_sco->state = BTA_AG_SCO_CLOSING_ST; + break; + + case BTA_AG_SCO_SHUTDOWN_E: + /* clear xfer scb */ + p_sco->p_xfer_scb = NULL; + + p_sco->state = BTA_AG_SCO_SHUTTING_ST; + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* closed sco; place old sco in listen mode, + take current sco out of listen, and + create originating sco for current */ + bta_ag_create_sco(p_scb, FALSE); + bta_ag_remove_sco(p_sco->p_xfer_scb, FALSE); + +#if (BTM_WBS_INCLUDED == TRUE ) + /* start codec negotiation */ + p_sco->state = BTA_AG_SCO_CODEC_ST; + p_cn_scb = p_sco->p_xfer_scb; + p_sco->p_xfer_scb = NULL; +#else + /* create sco connection to peer */ + bta_ag_create_sco(p_sco->p_xfer_scb, TRUE); + p_sco->p_xfer_scb = NULL; + p_sco->state = BTA_AG_SCO_OPENING_ST; +#endif + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d", event); + break; + } + break; + + case BTA_AG_SCO_SHUTTING_ST: + switch (event) + { + case BTA_AG_SCO_CONN_OPEN_E: + /* close sco connection; wait for conn close event */ + bta_ag_remove_sco(p_scb, TRUE); + break; + + case BTA_AG_SCO_CONN_CLOSE_E: + /* If last SCO instance then finish shutting down */ + if (!bta_ag_other_scb_open(p_scb)) + { + p_sco->state = BTA_AG_SCO_SHUTDOWN_ST; + } + else /* Other instance is still listening */ + { + p_sco->state = BTA_AG_SCO_LISTEN_ST; + } + + if (p_scb == p_sco->p_curr_scb) + { + p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX; + p_sco->p_curr_scb = NULL; + } + break; + + case BTA_AG_SCO_LISTEN_E: + /* create sco listen connection (Additional channel) */ + if (p_scb != p_sco->p_curr_scb) + { + bta_ag_create_sco(p_scb, FALSE); + } + break; + + case BTA_AG_SCO_SHUTDOWN_E: + if (!bta_ag_other_scb_open(p_scb)) + { + p_sco->state = BTA_AG_SCO_SHUTDOWN_ST; + } + else /* Other instance is still listening */ + { + p_sco->state = BTA_AG_SCO_LISTEN_ST; + } + + if (p_scb == p_sco->p_curr_scb) + { + p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX; + p_sco->p_curr_scb = NULL; + } + break; + + default: + APPL_TRACE_WARNING1("BTA_AG_SCO_SHUTTING_ST: Ignoring event %d", event); + break; + } + break; + + default: + break; + } +#if BTA_AG_SCO_DEBUG == TRUE + if (p_sco->state != in_state) + { + APPL_TRACE_EVENT3("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]", + bta_ag_sco_state_str(in_state), + bta_ag_sco_state_str(p_sco->state), + bta_ag_sco_evt_str(event)); + } +#endif + +#if (BTM_WBS_INCLUDED == TRUE ) + if (p_cn_scb) + { + bta_ag_codec_negotiate(p_cn_scb); + } +#endif +} + +/******************************************************************************* +** +** Function bta_ag_sco_is_open +** +** Description Check if sco is open for this scb. +** +** +** Returns TRUE if sco open for this scb, FALSE otherwise. +** +*******************************************************************************/ +BOOLEAN bta_ag_sco_is_open(tBTA_AG_SCB *p_scb) +{ + return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) && + (bta_ag_cb.sco.p_curr_scb == p_scb)); +} + +/******************************************************************************* +** +** Function bta_ag_sco_is_opening +** +** Description Check if sco is in Opening state. +** +** +** Returns TRUE if sco is in Opening state for this scb, FALSE otherwise. +** +*******************************************************************************/ +BOOLEAN bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb) +{ +#if (BTM_WBS_INCLUDED == TRUE ) + return (((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) || + (bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST)) && + (bta_ag_cb.sco.p_curr_scb == p_scb)); +#else + return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) && + (bta_ag_cb.sco.p_curr_scb == p_scb)); +#endif +} + +/******************************************************************************* +** +** Function bta_ag_sco_listen +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E); +} + +/******************************************************************************* +** +** Function bta_ag_sco_open +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + UINT8 event; + + /* if another scb using sco, this is a transfer */ + if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb) + { + event = BTA_AG_SCO_XFER_E; + } + /* else it is an open */ + else + { + event = BTA_AG_SCO_OPEN_E; + } + + bta_ag_sco_event(p_scb, event); +} + +/******************************************************************************* +** +** Function bta_ag_sco_close +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + /* if scb is in use */ +#if (BTM_WBS_INCLUDED == TRUE ) + /* sco_idx is not allocated in SCO_CODEC_ST, we still need to move to listening state. */ + if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) || (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST)) +#else + if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) +#endif + { + APPL_TRACE_DEBUG1("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx); + bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E); + } +} + +#if (BTM_WBS_INCLUDED == TRUE ) + +/******************************************************************************* +** +** Function bta_ag_sco_codec_nego +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result) +{ + if(result == TRUE) + { + /* Subsequent sco connection will skip codec negotiation */ + p_scb->codec_updated = FALSE; + + bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E); + } + else /* codec negotiation failed */ + bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E); +} +#endif + +/******************************************************************************* +** +** Function bta_ag_sco_shutdown +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E); +} + +/******************************************************************************* +** +** Function bta_ag_sco_conn_open +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E); + + bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + + bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_ON); + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + /* open SCO codec if SCO is routed through transport */ + bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE, BTA_AG_CI_SCO_DATA_EVT); +#endif + + /* call app callback */ + bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT); + + p_scb->retry_with_sco_only = FALSE; +} + +/******************************************************************************* +** +** Function bta_ag_sco_conn_close +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ + UINT16 handle = bta_ag_scb_to_idx(p_scb); + + /* clear current scb */ + bta_ag_cb.sco.p_curr_scb = NULL; + p_scb->sco_idx = BTM_INVALID_SCO_INDEX; + +#if (BTM_WBS_INCLUDED == TRUE) + /* codec_fallback is set when AG is initiator and connection failed for mSBC. */ + if (p_scb->codec_fallback && p_scb->svc_conn) + { + bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E); + } + else if (p_scb->retry_with_sco_only && p_scb->svc_conn) + { + /* retry_with_sco_only is set when AG is initiator and connection failed for eSCO */ + bta_ag_create_sco(p_scb, TRUE); + } +#else + /* retry_with_sco_only, will be set only when AG is initiator + ** and AG is first trying to establish an eSCO connection */ + if (p_scb->retry_with_sco_only && p_scb->svc_conn) + { + bta_ag_create_sco(p_scb, TRUE); + } +#endif + else + { + /* Indicate if the closing of audio is because of transfer */ + if (bta_ag_cb.sco.p_xfer_scb) + bta_ag_co_audio_state(handle, p_scb->app_id, BTA_AG_CO_AUD_STATE_OFF_XFER); + else + bta_ag_co_audio_state(handle, p_scb->app_id, BTA_AG_CO_AUD_STATE_OFF); + + bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E); + + bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + + /* if av got suspended by this call, let it resume. */ + /* In case call stays alive regardless of sco, av should not be affected. */ + if(((p_scb->call_ind == BTA_AG_CALL_INACTIVE) && (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE)) + || (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)) + { + bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + } + + /* call app callback */ + bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT); + } + p_scb->retry_with_sco_only = FALSE; +} + +/******************************************************************************* +** +** Function bta_ag_sco_conn_rsp +** +** Description Process the SCO connection request +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data) +{ + tBTM_ESCO_PARAMS resp; + UINT8 hci_status = HCI_SUCCESS; +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + tBTA_CODEC_INFO codec_info = {BTA_SCO_CODEC_PCM}; + UINT32 pcm_sample_rate; +#endif + + if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST || + bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST || + bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST) + { + /* If script overrided sco parameter by BTA_CMD_SET_ESCO_PARAM */ + if (bta_ag_cb.sco.param_updated) + { + resp = bta_ag_cb.sco.params; + } + else + { + resp.rx_bw = BTM_64KBITS_RATE; + resp.tx_bw = BTM_64KBITS_RATE; + resp.max_latency = 10; + resp.voice_contfmt = 0x60; + resp.retrans_effort = BTM_ESCO_RETRANS_POWER; + + if (p_data->link_type == BTM_LINK_TYPE_SCO) + { + resp.packet_types = (BTM_SCO_LINK_ONLY_MASK | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV5); + } + else /* Allow controller to use all types available except 5-slot EDR */ + { + resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK | + BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | + BTM_SCO_PKT_TYPES_MASK_NO_3_EV5); + } + } + + /* tell sys to stop av if any */ + bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); + + /* Allow any platform specific pre-SCO set up to take place */ + bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP); + +#if (BTM_WBS_INCLUDED == TRUE ) + /* When HS initiated SCO, it cannot be WBS. */ + BTM_ConfigI2SPCM (BTM_SCO_CODEC_CVSD, (UINT8)HCI_BRCM_I2SPCM_IS_DEFAULT_ROLE, (UINT8)HCI_BRCM_I2SPCM_SAMPLE_DEFAULT, (UINT8)HCI_BRCM_I2SPCM_CLOCK_DEFAULT); +#endif + +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K; + + /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */ + BTM_ConfigScoPath(bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id), + bta_ag_sco_read_cback, NULL, TRUE); +#endif + } + else + hci_status = HCI_ERR_HOST_REJECT_DEVICE; + +#if (BTM_WBS_INCLUDED == TRUE ) + /* If SCO open was initiated from HS, it must be CVSD */ + p_scb->inuse_codec = BTA_AG_CODEC_NONE; +#endif + + BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp); +} + +/******************************************************************************* +** +** Function bta_ag_ci_sco_data +** +** Description Process the SCO data ready callin event +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) +{ +#if (BTM_SCO_HCI_INCLUDED == TRUE ) + bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E); +#endif +} + +/******************************************************************************* +** +** Function bta_ag_set_esco_param +** +** Description Update esco parameters from script wrapper. +** +** +** Returns void +** +*******************************************************************************/ +void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param) +{ + if(set_reset == FALSE) /* reset the parameters to default */ + { + bta_ag_cb.sco.param_updated = FALSE; + APPL_TRACE_DEBUG0("bta_ag_set_esco_param : Resetting ESCO parameters to default"); + } + else + { + bta_ag_cb.sco.param_updated = TRUE; + bta_ag_cb.sco.params = *param; + APPL_TRACE_DEBUG0("bta_ag_set_esco_param : Setting ESCO parameters"); + } +} + +/******************************************************************************* +** Debugging functions +*******************************************************************************/ + +#if BTA_AG_SCO_DEBUG == TRUE +static char *bta_ag_sco_evt_str(UINT8 event) +{ + switch (event) + { + case BTA_AG_SCO_LISTEN_E: + return "Listen Request"; + case BTA_AG_SCO_OPEN_E: + return "Open Request"; + case BTA_AG_SCO_XFER_E: + return "Transfer Request"; +#if (BTM_WBS_INCLUDED == TRUE ) + case BTA_AG_SCO_CN_DONE_E: + return "Codec Negotiation Done"; + case BTA_AG_SCO_REOPEN_E: + return "Reopen Request"; +#endif + case BTA_AG_SCO_CLOSE_E: + return "Close Request"; + case BTA_AG_SCO_SHUTDOWN_E: + return "Shutdown Request"; + case BTA_AG_SCO_CONN_OPEN_E: + return "Opened"; + case BTA_AG_SCO_CONN_CLOSE_E: + return "Closed"; + case BTA_AG_SCO_CI_DATA_E : + return "Sco Data"; + default: + return "Unknown SCO Event"; + } +} + +static char *bta_ag_sco_state_str(UINT8 state) +{ + switch (state) + { + case BTA_AG_SCO_SHUTDOWN_ST: + return "Shutdown"; + case BTA_AG_SCO_LISTEN_ST: + return "Listening"; +#if (BTM_WBS_INCLUDED == TRUE ) + case BTA_AG_SCO_CODEC_ST: + return "Codec Negotiation"; +#endif + case BTA_AG_SCO_OPENING_ST: + return "Opening"; + case BTA_AG_SCO_OPEN_CL_ST: + return "Open while closing"; + case BTA_AG_SCO_OPEN_XFER_ST: + return "Opening while Transferring"; + case BTA_AG_SCO_OPEN_ST: + return "Open"; + case BTA_AG_SCO_CLOSING_ST: + return "Closing"; + case BTA_AG_SCO_CLOSE_OP_ST: + return "Close while Opening"; + case BTA_AG_SCO_CLOSE_XFER_ST: + return "Close while Transferring"; + case BTA_AG_SCO_SHUTTING_ST: + return "Shutting Down"; + default: + return "Unknown SCO State"; + } +} + +#endif diff --git a/bta/ag/bta_ag_sdp.c b/bta/ag/bta_ag_sdp.c new file mode 100644 index 0000000..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 +#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 +#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; xxseps[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; xxseps[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, + ×tamp); + + if (p_buf) + { + /* use the offset area for the time stamp */ + *(UINT32 *)(p_buf + 1) = timestamp; + + /* dup the data to other channels */ + bta_av_dup_audio_buf(p_scb, p_buf); + } + } + + if(p_buf) + { + if(p_scb->l2c_bufs < (BTA_AV_QUEUE_DATA_CHK_NUM)) + { + /* there's a buffer, just queue it to L2CAP */ + /* There's no need to increment it here, it is always read from L2CAP see above */ + /* p_scb->l2c_bufs++; */ + /* + APPL_TRACE_ERROR1("qw: %d", p_scb->l2c_bufs); + */ + AVDT_WriteReq(p_scb->avdt_handle, p_buf, timestamp, m_pt); + p_scb->cong = TRUE; + } + else + { + /* there's a buffer, but L2CAP does not seem to be moving data */ + if(new_buf) + { + /* just got this buffer from co_data, + * put it in queue */ + GKI_enqueue(&p_scb->q_info.a2d, p_buf); + } + else + { + /* just dequeue it from the q_info.a2d */ + if(p_scb->q_info.a2d.count < 3) + { + /* put it back to the queue */ + GKI_enqueue_head (&p_scb->q_info.a2d, p_buf); + } + else + { + /* too many buffers in q_info.a2d, drop it. */ + bta_av_co_audio_drop(p_scb->hndl); + GKI_freebuf(p_buf); + } + } + } + } + } +} + +/******************************************************************************* +** +** Function bta_av_start_ok +** +** Description Stream started. +** +** Returns void +** +*******************************************************************************/ +void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) +{ + tBTA_AV_START start; + tBTA_AV_API_STOP stop; + BOOLEAN initiator = FALSE; + BOOLEAN suspend = FALSE; + UINT16 flush_to; + UINT8 new_role = p_scb->role; + BT_HDR hdr; + + APPL_TRACE_DEBUG2("bta_av_start_ok wait:x%x, role:x%x", p_scb->wait, p_scb->role); + + p_scb->started = TRUE; + if (p_scb->sco_suspend) + { + p_scb->sco_suspend = FALSE; + } + + if (new_role & BTA_AV_ROLE_START_INT) + initiator = TRUE; + + if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_FAILED) + { + /* role switch has failed */ + p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_FAILED; + p_data = (tBTA_AV_DATA *)&hdr; + hdr.offset = BTA_AV_RS_FAIL; + } + APPL_TRACE_DEBUG1("wait:x%x", p_scb->wait); + + if (p_data && (p_data->hdr.offset != BTA_AV_RS_NONE)) + { + p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS; + if (p_data->hdr.offset == BTA_AV_RS_FAIL) + { + bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); + start.chnl = p_scb->chnl; + start.status = BTA_AV_FAIL_ROLE; + start.hndl = p_scb->hndl; + start.initiator = initiator; + (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start); + return; + } + } + + if (!bta_av_link_role_ok(p_scb, A2D_SET_ONE_BIT)) + p_scb->q_tag = BTA_AV_Q_TAG_START; + else + { + /* The wait flag may be set here while we are already master on the link */ + /* this could happen if a role switch complete event occurred during reconfig */ + /* if we are now master on the link, there is no need to wait for the role switch, */ + /* complete anymore so we can clear the wait for role switch flag */ + p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS; + } + + if (p_scb->wait & (BTA_AV_WAIT_ROLE_SW_RES_OPEN|BTA_AV_WAIT_ROLE_SW_RES_START)) + { + p_scb->wait |= BTA_AV_WAIT_ROLE_SW_STARTED; + p_scb->q_tag = BTA_AV_Q_TAG_START; + } + + if (p_scb->wait & BTA_AV_WAIT_ACP_CAPS_ON) + { + p_scb->wait |= BTA_AV_WAIT_ACP_CAPS_STARTED; + } + + if (p_scb->wait) + { + APPL_TRACE_DEBUG2("wait:x%x q_tag:%d- not started", p_scb->wait, p_scb->q_tag); + return; + } + + /* tell role manager to check M/S role */ + bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr); + + bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr); + + if(p_scb->media_type == AVDT_MEDIA_AUDIO) + { + /* in normal logic, conns should be bta_av_cb.audio_count - 1, + * However, bta_av_stream_chg is not called to increase bta_av_cb.audio_count yet. + * If the code were to be re-arranged for some reasons, this number may need to be changed + */ + p_scb->co_started = bta_av_cb.audio_open_cnt; + flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1]; + } + else + { + flush_to = p_bta_av_cfg->video_flush_to; + } + L2CA_SetFlushTimeout(p_scb->peer_addr, flush_to ); + + /* clear the congestion flag */ + p_scb->cong = FALSE; + + if (new_role & BTA_AV_ROLE_START_INT) + { + new_role &= ~BTA_AV_ROLE_START_INT; + } + else if ((new_role & BTA_AV_ROLE_AD_ACP) && (new_role & BTA_AV_ROLE_SUSPEND_OPT)) + { + suspend = TRUE; + } + + if (!suspend) + { + p_scb->q_tag = BTA_AV_Q_TAG_STREAM; + bta_av_stream_chg(p_scb, TRUE); + } + + { + p_scb->role = new_role; + p_scb->role &= ~BTA_AV_ROLE_AD_ACP; + p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT; + + p_scb->p_cos->start(p_scb->hndl, p_scb->codec_type); + p_scb->co_started = TRUE; + + APPL_TRACE_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; ichnl == 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 +#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; ihandle != 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; idisabling == 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; xxconn_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; ip_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; xxnum_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; ihdi); + 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 (; ipeer_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; ilidx) + { + 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; iconn_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; ichnl == 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; xxapi_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; xxconn_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; xxconn_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; ircb[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 + +/***************************************************************************** +** 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 + +/******************************************************************************* +** +** 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 +#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; xxtimer)== 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; iapi_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; xxpeer_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; xxrc_handle = BTA_AV_RC_HANDLE_NONE; + p_ret->chnl = chnl; + p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl); + p_ret->hdi = xx; + bta_av_cb.p_scb[xx] = p_ret; + } + break; + } + } + } + return p_ret; +} + +/******************************************************************************* +*******************************************************************************/ +void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data) +{ + tBTA_AV_STR_MSG *p_msg; + UINT16 evt = 0; + tBTA_AV_SCB *p_scb = NULL; + +#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) + if (event == BTA_AR_AVDT_CONN_EVT || + event == AVDT_CONNECT_IND_EVT || event == AVDT_DISCONNECT_IND_EVT) +#else + if (event == AVDT_CONNECT_IND_EVT || event == AVDT_DISCONNECT_IND_EVT) +#endif + { + evt = BTA_AV_SIG_CHG_EVT; + if(AVDT_DISCONNECT_IND_EVT == event) + p_scb = bta_av_addr_to_scb(bd_addr); +#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE) + else if (AVDT_CONNECT_IND_EVT == event) + { + APPL_TRACE_DEBUG1("CONN_IND is ACP:%d", p_data->hdr.err_param); + } +#endif + + if (/*((p_scb && (p_scb->role & BTA_AV_ROLE_AD_ACP)) || + + //(AVDT_CONNECT_IND_EVT == event && AVDT_ACP == p_data->hdr.err_param)) + + (AVDT_CONNECT_IND_EVT == event))&& */ + (p_msg = (tBTA_AV_STR_MSG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_STR_MSG)))) != NULL) + { + p_msg->hdr.event = evt; + p_msg->hdr.layer_specific = event; + p_msg->hdr.offset = p_data->hdr.err_param; + bdcpy(p_msg->bd_addr, bd_addr); +#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE) + if(p_scb) + { + APPL_TRACE_DEBUG2("scb hndl x%x, role x%x", p_scb->hndl, p_scb->role); + } +#endif + APPL_TRACE_DEBUG6("conn_cback bd_addr:%02x-%02x-%02x-%02x-%02x-%02x", + bd_addr[0], bd_addr[1], + bd_addr[2], bd_addr[3], + bd_addr[4], bd_addr[5]); + bta_sys_sendmsg(p_msg); + } + } + +} + +#if AVDT_REPORTING == TRUE +/******************************************************************************* +** +** Function bta_av_a2dp_report_cback +** +** Description A2DP report callback. +** +** Returns void +** +*******************************************************************************/ +static void bta_av_a2dp_report_cback(UINT8 handle, AVDT_REPORT_TYPE type, + tAVDT_REPORT_DATA *p_data) +{ + /* Do not need to handle report data for now. + * This empty function is here for conformance reasons. */ +} +#endif + +/******************************************************************************* +** +** Function bta_av_api_register +** +** Description allocate stream control block, +** register the service to stack +** create SDP record +** +** Returns void +** +*******************************************************************************/ +static void bta_av_api_register(tBTA_AV_DATA *p_data) +{ + tBTA_AV_REGISTER registr; + tBTA_AV_SCB *p_scb; /* stream control block */ + tAVDT_REG reg; + tAVDT_CS cs; + char *p_service_name; + tBTA_AV_CODEC codec_type; + tBTA_UTL_COD cod; + UINT8 index = 0; + + memset(&cs,0,sizeof(tAVDT_CS)); + + registr.status = BTA_AV_FAIL_RESOURCES; + registr.app_id = p_data->api_reg.app_id; + registr.chnl = (tBTA_AV_CHNL)p_data->hdr.layer_specific; + do + { + p_scb = bta_av_alloc_scb(registr.chnl); + if(p_scb == NULL) + { + APPL_TRACE_ERROR0("failed to alloc SCB"); + break; + } + + registr.hndl = p_scb->hndl; + p_scb->app_id = registr.app_id; + + /* initialize the stream control block */ + p_scb->timer.p_cback = (TIMER_CBACK*)&bta_av_timer_cback; + registr.status = BTA_AV_SUCCESS; + + if((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0) + { + /* the first channel registered. register to AVDTP */ + reg.ctrl_mtu = p_bta_av_cfg->sig_mtu; + reg.ret_tout = BTA_AV_RET_TOUT; + reg.sig_tout = BTA_AV_SIG_TOUT; + reg.idle_tout = BTA_AV_IDLE_TOUT; + reg.sec_mask = bta_av_cb.sec_mask; +#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) + bta_ar_reg_avdt(®, bta_av_conn_cback, BTA_ID_AV); +#endif + bta_sys_role_chg_register(&bta_av_sys_rs_cback); + + /* create remote control TG service if required */ + if (bta_av_cb.features & (BTA_AV_FEAT_RCTG)) + { + /* register with no authorization; let AVDTP use authorization instead */ +#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE) +#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE) + bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu, + bta_av_cb.sec_mask, BTA_ID_AV); +#else + bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu, + (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV); +#endif + + bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", NULL, + p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV); +#endif + } + + /* Set the Capturing service class bit */ + cod.service = BTM_COD_SERVICE_CAPTURING; + utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS); + } /* if 1st channel */ + + /* get stream configuration and create stream */ + /* memset(&cs.cfg,0,sizeof(tAVDT_CFG)); */ + cs.cfg.num_codec = 1; + cs.tsep = AVDT_TSEP_SRC; + + /* + * memset of cs takes care setting call back pointers to null. + cs.p_data_cback = NULL; + cs.p_report_cback = NULL; + */ + cs.nsc_mask = AVDT_NSC_RECONFIG | + ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY); + APPL_TRACE_DEBUG1("nsc_mask: 0x%x", cs.nsc_mask); + + if (p_data->api_reg.p_service_name[0] == 0) + { + p_service_name = NULL; + } + else + { + p_service_name = p_data->api_reg.p_service_name; + } + + p_scb->suspend_sup = TRUE; + p_scb->recfg_sup = TRUE; + + cs.p_ctrl_cback = bta_av_dt_cback[p_scb->hdi]; + if(registr.chnl == BTA_AV_CHNL_AUDIO) + { + /* set up the audio stream control block */ + p_scb->p_act_tbl = (const tBTA_AV_ACT *)bta_av_a2d_action; + p_scb->p_cos = &bta_av_a2d_cos; + p_scb->media_type= AVDT_MEDIA_AUDIO; + cs.cfg.psc_mask = AVDT_PSC_TRANS; + cs.media_type = AVDT_MEDIA_AUDIO; + cs.mtu = p_bta_av_cfg->audio_mtu; + cs.flush_to = L2CAP_DEFAULT_FLUSH_TO; +#if AVDT_REPORTING == TRUE + if(bta_av_cb.features & BTA_AV_FEAT_REPORT) + { + cs.cfg.psc_mask |= AVDT_PSC_REPORT; + cs.p_report_cback = bta_av_a2dp_report_cback; +#if AVDT_MULTIPLEXING == TRUE + cs.cfg.mux_tsid_report = 2; +#endif + } +#endif + if(bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT) + cs.cfg.psc_mask |= AVDT_PSC_DELAY_RPT; + + /* keep the configuration in the stream control block */ + memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG)); + while(index < BTA_AV_MAX_SEPS && + (*bta_av_a2d_cos.init)(&codec_type, cs.cfg.codec_info, + &cs.cfg.num_protect, cs.cfg.protect_info, index) == TRUE) + { + if(AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS) + { + p_scb->seps[index].codec_type = codec_type; + APPL_TRACE_DEBUG3("audio[%d] av_handle: %d codec_type: %d", + index, p_scb->seps[index].av_handle, p_scb->seps[index].codec_type); + index++; + } + else + break; + } + + if(!bta_av_cb.reg_audio) + { + /* create the SDP records on the 1st audio channel */ + bta_av_cb.sdp_a2d_handle = SDP_CreateRecord(); + A2D_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL, + A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_handle); + bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE); + + /* start listening when A2DP is registered */ + if (bta_av_cb.features & BTA_AV_FEAT_RCTG) + bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); + + /* if the AV and AVK are both supported, it cannot support the CT role */ +#if (BTA_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 *)®istr); +} + +/******************************************************************************* +** +** Function bta_av_api_deregister +** +** Description de-register a channel +** +** +** Returns void +** +*******************************************************************************/ +void bta_av_api_deregister(tBTA_AV_DATA *p_data) +{ + tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific); + + if(p_scb) + { + p_scb->deregistring = TRUE; + bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, p_data); + } + else + { + bta_av_dereg_comp(p_data); + } +} + +/******************************************************************************* +** +** Function bta_av_ci_data +** +** Description forward the BTA_AV_CI_SRC_DATA_READY_EVT to stream state machine +** +** +** Returns void +** +*******************************************************************************/ +static void bta_av_ci_data(tBTA_AV_DATA *p_data) +{ + tBTA_AV_SCB *p_scb; + int i; + UINT8 chnl = (UINT8)p_data->hdr.layer_specific; + + for( i=0; i < BTA_AV_NUM_STRS; i++ ) + { + p_scb = bta_av_cb.p_scb[i]; + + if(p_scb && p_scb->chnl == chnl) + { + bta_av_ssm_execute(p_scb, BTA_AV_SRC_DATA_READY_EVT, p_data); + } + } +} + +/******************************************************************************* +** +** Function bta_av_rpc_conn +** +** Description report report channel open +** +** Returns void +** +*******************************************************************************/ +#if (AVDT_REPORTING == TRUE) +static void bta_av_rpc_conn(tBTA_AV_DATA *p_data) +{ + 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; xxchnl == 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; ichnl == 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; iconn_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; ipeer_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; ico_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; isco_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; ihdi != 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; ichnl == 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; ihdi != 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 +#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 +#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 +#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 +#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 + +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; iset_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<tm &= (UINT32)(~(1<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; ievent = 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; iconn_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; ihdr.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 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 + +/***************************************************************************** +** 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 +#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 + + +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 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; jpm_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; ipeer_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; ipm_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; imax_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; ihdr.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; ipeer_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 +#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 + +#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 +#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, ¶m); + 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, ¶m); + } + + /* 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, ¶m); + + /* 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, ¶m); + } + } + 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, ¶m); + + /* 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, ¶m); +} + +/******************************************************************************* +** +** 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 +#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 + +#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 +#include +#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 ( "\n" \ + "\n" \ + "\n" ) + +#define BTA_FTC_FOLDER_LISTING_END ( "" ) + +#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(¶m, 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 +#include +#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 +#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 + +#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 = ⌖ + + /* 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 + +#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 +#include +#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 ( "\n" \ + "\n" \ + "\n" ) + +#define BTA_FTS_FOLDER_LISTING_END ( "" ) +#define BTA_FTS_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, ¶m); + } + } + 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, ¶m); + } + + /* 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 + +/***************************************************************************** +** Constants +*****************************************************************************/ +static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id, + BOOLEAN connected, tGATT_DISCONN_REASON reason); + +static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, + tGATT_CL_COMPLETE *p_data); + +static tGATT_CBACK bta_gattc_cl_cback = +{ + bta_gattc_conn_cback, + bta_gattc_cmpl_cback, + bta_gattc_disc_res_cback, + bta_gattc_disc_cmpl_cback, + NULL +}; + +/* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */ +static UINT16 bta_gattc_opcode_to_int_evt[] = +{ + BTA_GATTC_API_READ_EVT, + BTA_GATTC_API_WRITE_EVT, + BTA_GATTC_API_EXEC_EVT +}; + +#if (BT_TRACE_VERBOSE == TRUE) +static const char *bta_gattc_op_code_name[] = +{ + "Unknown", + "Discovery", + "Read", + "Write", + "Exec", + "Config", + "Notification", + "Indication" +}; +#endif +/***************************************************************************** +** Action Functions +*****************************************************************************/ + +/******************************************************************************* +** +** Function bta_gattc_register +** +** Description Register a GATT client application with BTA. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATTC cb_data; + UINT8 i; + tBT_UUID *p_app_uuid = &p_data->api_reg.app_uuid; + tBTA_GATTC_INT_START_IF *p_buf; + + + /* todo need to check duplicate uuid */ + for (i = 0; i < BTA_GATTC_CL_MAX; i ++) + { + if (!p_cb->cl_rcb[i].in_use) + { + if ((p_app_uuid == NULL) || (p_cb->cl_rcb[i].client_if = GATT_Register(p_app_uuid, &bta_gattc_cl_cback)) == 0) + { + APPL_TRACE_ERROR0("Register with GATT stack failed."); + cb_data.reg_oper.status = BTA_GATT_ERROR; + } + else + + { + p_cb->cl_rcb[i].in_use = TRUE; + p_cb->cl_rcb[i].p_cback = p_data->api_reg.p_cback; + memcpy(&p_cb->cl_rcb[i].app_uuid, p_app_uuid, sizeof(tBT_UUID)); + + /* BTA use the same client interface as BTE GATT statck */ + cb_data.reg_oper.client_if = p_cb->cl_rcb[i].client_if; +// btla-specific ++ + memcpy(&(cb_data.reg_oper.app_uuid),p_app_uuid,sizeof(tBT_UUID)); +// btla-specific -- + + cb_data.reg_oper.status = BTA_GATT_OK; + + if ((p_buf = (tBTA_GATTC_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTC_INT_START_IF))) != NULL) + { + p_buf->hdr.event = BTA_GATTC_INT_START_IF_EVT; + p_buf->client_if = p_cb->cl_rcb[i].client_if; + + bta_sys_sendmsg(p_buf); + } + else + { + cb_data.reg_oper.status = BTA_GATT_NO_RESOURCES; + memset( &p_cb->cl_rcb[i], 0 , sizeof(tBTA_GATTC_RCB)); + } + break; + } + } + } + /* callback with register event */ + if (p_data->api_reg.p_cback) + { + (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT, (tBTA_GATTC *)&cb_data); + } +} + +/******************************************************************************* +** +** Function bta_gattc_start_if +** +** Description start an application interface. +** +** Returns none. +** +*******************************************************************************/ +void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg) +{ + if (bta_gattc_cl_get_regcb(p_msg->int_start_if.client_if) !=NULL ) + { + GATT_StartIf(p_msg->int_start_if.client_if); + } + else + { + APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.client_if ); + } +} + + +/******************************************************************************* +** +** Function bta_gattc_deregister_cmpl +** +** Description De-Register a GATT client application with BTA completed. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_int_deregister_cmpl(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_IF client_if) +{ + tBTA_GATTC_CBACK *p_cback = p_clreg->p_cback; + tBTA_GATTC cb_data; + + + APPL_TRACE_DEBUG1("bta_gattc_int_deregister_cmpl client_if=%d", client_if ); + + GATT_Deregister(p_clreg->client_if); + memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB)); + + cb_data.reg_oper.client_if = client_if; + cb_data.reg_oper.status = BTA_GATT_OK; + + if (p_cback) + /* callback with de-register event */ + (*p_cback)(BTA_GATTC_DEREG_EVT, (tBTA_GATTC *)&cb_data); +} + + +/******************************************************************************* +** +** Function bta_gattc_deregister_cmpl +** +** Description De-Register a GATT client application with BTA completed. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_IF client_if) +{ + tBTA_GATTC_INT_DEREG *p_buf; + + APPL_TRACE_DEBUG1("bta_gattc_deregister_cmpl client_if=%d", client_if ); + + if ((p_buf = (tBTA_GATTC_INT_DEREG *) GKI_getbuf(sizeof(tBTA_GATTC_INT_DEREG))) != NULL) + { + p_buf->hdr.event = BTA_GATTC_INT_DEREG_EVT; + p_buf->client_if = client_if; + bta_sys_sendmsg(p_buf); + } + else + { + APPL_TRACE_ERROR1("bta_gattc_deregister_cmpl unable to allocate buffer to complete dereg=%d", client_if); + } + +} + +/******************************************************************************* +** +** Function bta_gattc_deregister +** +** Description De-Register a GATT client application with BTA. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_int_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data) +{ + + tBTA_GATTC_IF client_if = p_data->int_dereg.client_if; + tBTA_GATTC_CBACK *p_cback; + tBTA_GATTC cb_data; + tBTA_GATTC_RCB *p_clreg; + + + APPL_TRACE_DEBUG1("bta_gattc_int_deregister_cmpl client_if=%d", client_if ); + + if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL) + { + p_cback = p_clreg->p_cback; + GATT_Deregister(client_if); + memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB)); + cb_data.reg_oper.client_if = client_if; + cb_data.reg_oper.status = BTA_GATT_OK; + + if (p_cback) + /* callback with de-register event */ + (*p_cback)(BTA_GATTC_DEREG_EVT, (tBTA_GATTC *)&cb_data); + } + else + { + APPL_TRACE_ERROR1("bta_gattc_int_deregister Deregister Failed, unknown client_if: %d", p_data->int_dereg.client_if); + } +} + + +/******************************************************************************* +** +** Function bta_gattc_deregister +** +** Description De-Register a GATT client application with BTA. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATTC_RCB *p_clreg; + UINT8 i; + BT_HDR buf; + + if ((p_clreg = bta_gattc_cl_get_regcb(p_data->api_dereg.client_if)) != NULL) + { + if (p_clreg->num_clcb > 0) + { + /* close all CLCB related to this app */ + for (i= 0; i < BTA_GATTC_CLCB_MAX; i ++) + { + if (p_cb->clcb[i].in_use && (p_cb->clcb[i].p_rcb == p_clreg)) + { + p_clreg->dereg_pending = TRUE; + + buf.event = BTA_GATTC_API_CLOSE_EVT; + buf.layer_specific = p_cb->clcb[i].bta_conn_id; + bta_gattc_close(&p_cb->clcb[i], (tBTA_GATTC_DATA *)&buf) ; + } + } + } + else + bta_gattc_deregister_cmpl(p_clreg, p_clreg->client_if); + } + else + { + APPL_TRACE_ERROR1("bta_gattc_deregister Deregister Failed, unknown client_if: %d", p_data->api_dereg.client_if); + } +} +/******************************************************************************* +** +** Function bta_gattc_process_api_open +** +** Description process connect API request. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg) +{ + UINT16 event = ((BT_HDR *)p_msg)->event; + tBTA_GATTC_CLCB *p_clcb = NULL; + tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_conn.client_if); + + if (p_clreg != NULL) + { + if (p_msg->api_conn.is_direct) + { + if ((p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if, + p_msg->api_conn.remote_bda)) != NULL) + { + bta_gattc_sm_execute(p_clcb, event, p_msg); + } + else + { + APPL_TRACE_ERROR0("No resources to open a new connection."); + + bta_gattc_send_open_cback(p_clreg, + BTA_GATT_NO_RESOURCES, + p_msg->api_conn.remote_bda, + BTA_GATT_INVALID_CONN_ID); + } + } + else + { + bta_gattc_init_bk_conn(&p_msg->api_conn, p_clreg); + } + } + else + { + APPL_TRACE_ERROR1("bta_gattc_process_api_open Failed, unknown client_if: %d", + p_msg->api_conn.client_if); + } +} +/******************************************************************************* +** +** Function bta_gattc_process_api_open_cancel +** +** Description process connect API request. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg) +{ + UINT16 event = ((BT_HDR *)p_msg)->event; + tBTA_GATTC_CLCB *p_clcb = NULL; + tBTA_GATTC_RCB *p_clreg; + tBTA_GATT_STATUS status = BTA_GATT_ERROR; + + if (p_msg->api_cancel_conn.is_direct) + { + if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->api_cancel_conn.client_if, + p_msg->api_cancel_conn.remote_bda)) != NULL) + { + bta_gattc_sm_execute(p_clcb, event, p_msg); + } + else + { + APPL_TRACE_ERROR0("No such connection need to be cancelled"); + + p_clreg = bta_gattc_cl_get_regcb(p_msg->api_cancel_conn.client_if); + + if (p_clreg && p_clreg->p_cback) + { + (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status); + } + } + } + else + { + bta_gattc_cancel_bk_conn(&p_msg->api_cancel_conn); + + } +} + +/******************************************************************************* +** +** Function bta_gattc_cancel_open_error +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATT_STATUS status=BTA_GATT_ERROR; + + if ( p_clcb->p_rcb->p_cback ) + (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status); +} + +/******************************************************************************* +** +** Function bta_gattc_open_error +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + APPL_TRACE_ERROR0("Connection already opened. wrong state"); + + bta_gattc_send_open_cback(p_clcb->p_rcb, + BTA_GATT_ALREADY_OPEN, + p_clcb->bda, + p_clcb->bta_conn_id); +} +/******************************************************************************* +** +** Function bta_gattc_open_fail +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_open_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + bta_gattc_open_error(p_clcb, p_data); + /* open failure, remove clcb */ + bta_gattc_clcb_dealloc(p_clcb); +} + +/******************************************************************************* +** +** Function bta_gattc_open +** +** Description Process API connection function. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATTC_DATA gattc_data; + + /* open/hold a connection */ + if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda, TRUE)) + { + APPL_TRACE_ERROR0("Connection open failure"); + + bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_OPEN_FAIL_EVT, p_data); + } + else + { + /* a connected remote device */ + if (GATT_GetConnIdIfConnected(p_clcb->p_rcb->client_if, + p_data->api_conn.remote_bda, + &p_clcb->bta_conn_id)) + { + gattc_data.hdr.layer_specific = p_clcb->bta_conn_id; + + bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data); + } + /* else wait for the callback event */ + } +} +/******************************************************************************* +** +** Function bta_gattc_init_bk_conn +** +** Description Process API Open for a background connection +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg) +{ + tBTA_GATT_STATUS status = BTA_GATT_NO_RESOURCES; + UINT16 conn_id; + tBTA_GATTC_CLCB *p_clcb; + tBTA_GATTC_DATA gattc_data; + + if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE)) + { + /* alwaya call open to hold a connection */ + if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE)) + { + status = BTA_GATT_ERROR; + APPL_TRACE_ERROR0("bta_gattc_init_bk_conn failed"); + } + else + { + status = BTA_GATT_OK; + + /* if is a connected remote device */ + if (GATT_GetConnIdIfConnected(p_data->client_if, + p_data->remote_bda, + &conn_id)) + { + if ((p_clcb = bta_gattc_clcb_alloc(p_data->client_if, p_data->remote_bda)) != NULL) + { + gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id; + + /* open connection */ + bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data); + status = BTA_GATT_OK; + } + } + } + } + + /* open failure, report OPEN_EVT */ + if (status != BTA_GATT_OK) + { + bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda, BTA_GATT_INVALID_CONN_ID); + } +} +/******************************************************************************* +** +** Function bta_gattc_cancel_bk_conn +** +** Description Process API Cancel Open for a background connection +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data) +{ + tBTA_GATTC_RCB *p_clreg; + tBTA_GATT_STATUS status = BTA_GATT_ERROR; + + /* remove the device from the bg connection mask */ + if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, FALSE)) + { + if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, FALSE)) + { + status = BTA_GATT_OK; + } + else + { + APPL_TRACE_ERROR0("bta_gattc_cancel_bk_conn failed"); + } + } + p_clreg = bta_gattc_cl_get_regcb(p_data->client_if); + + if (p_clreg && p_clreg->p_cback) + { + (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status); + } + +} +/******************************************************************************* +** +** Function bta_gattc_int_cancel_open_ok +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATT_STATUS status = BTA_GATT_OK; + + if ( p_clcb->p_rcb->p_cback ) + { + (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status); + } + + bta_gattc_clcb_dealloc(p_clcb); +} + +/******************************************************************************* +** +** Function bta_gattc_cancel_open +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATT_STATUS status=BTA_GATT_ERROR; + + if (GATT_CancelConnect(p_clcb->p_rcb->client_if, p_data->api_cancel_conn.remote_bda, TRUE)) + { + bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CANCEL_OPEN_OK_EVT, p_data); + } + else + { + if ( p_clcb->p_rcb->p_cback ) + { + (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status); + } + } +} +/******************************************************************************* +** +** Function bta_gattc_conn +** +** Description receive connection callback from stack +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATTC_IF gatt_if; + APPL_TRACE_DEBUG1("bta_gattc_conn server cache state=%d",p_clcb->p_srcb->state); + + if (p_data != NULL) + { + APPL_TRACE_DEBUG1("bta_gattc_conn conn_id=%d",p_data->hdr.layer_specific); + + p_clcb->p_srcb->connected = TRUE; + p_clcb->bta_conn_id = p_data->hdr.layer_specific; + GATT_GetConnectionInfor(p_data->hdr.layer_specific, &gatt_if, p_clcb->bda); + + /* start database cache if needed */ + if (p_clcb->p_srcb->p_srvc_cache == NULL) + { + if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) + { + p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD; + bta_gattc_sm_execute(p_clcb, BTA_GATTC_START_CACHE_EVT, p_data); + } + else /* cache is building */ + p_clcb->state = BTA_GATTC_DISCOVER_ST; + } + + else + { + /* a pending service handle change indication */ + if (p_clcb->p_srcb->srvc_hdl_chg) + { + p_clcb->p_srcb->srvc_hdl_chg = FALSE; + /* start discovery */ + bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); + } + } + + if (p_clcb->p_rcb) + { + bta_gattc_send_open_cback(p_clcb->p_rcb, + BTA_GATT_OK, + p_clcb->bda, + p_clcb->bta_conn_id); + } + } +} + +/******************************************************************************* +** +** Function bta_gattc_close_fail +** +** Description close a connection. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATTC cb_data; + + if ( p_clcb->p_rcb->p_cback ) + { + memset(&cb_data, 0, sizeof(tBTA_GATTC)); + cb_data.close.client_if = p_clcb->p_rcb->client_if; + cb_data.close.conn_id = p_data->hdr.layer_specific; + bdcpy(cb_data.close.remote_bda, p_clcb->bda); + cb_data.close.status = BTA_GATT_ERROR; + cb_data.close.reason = BTA_GATT_CONN_NONE; + + + (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CLOSE_EVT, &cb_data); + } +} +/******************************************************************************* +** +** Function bta_gattc_api_close +** +** Description close a GATTC connection. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATTC_CBACK *p_cback = p_clcb->p_rcb->p_cback; + tBTA_GATTC_RCB *p_clreg = p_clcb->p_rcb; + tBTA_GATTC cb_data; + + APPL_TRACE_DEBUG1("bta_gattc_close conn_id=%d",p_clcb->bta_conn_id); + + if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT) + p_clcb->status = GATT_Disconnect(p_clcb->bta_conn_id); + + cb_data.close.client_if = p_clcb->p_rcb->client_if; + cb_data.close.conn_id = p_clcb->bta_conn_id; + cb_data.close.status = p_clcb->status; + cb_data.close.reason = p_clcb->reason; + bdcpy(cb_data.close.remote_bda, p_clcb->bda); + + if (p_clcb->status == BTA_GATT_OK) + { + /* if the srcb is no longer needed, reset the state */ + if ( -- p_clcb->p_srcb->num_clcb == 0) + { + APPL_TRACE_DEBUG0("Update srcb connection status"); + p_clcb->p_srcb->connected = FALSE; + p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE; + } + + bta_gattc_clcb_dealloc(p_clcb); + } + + ( * p_cback)(BTA_GATTC_CLOSE_EVT, (tBTA_GATTC *)&cb_data); + + if (-- p_clreg->num_clcb == 0 && p_clreg->dereg_pending) + { + bta_gattc_deregister_cmpl(p_clreg, p_clreg->client_if); + } + +} + +/******************************************************************************* +** +** Function bta_gattc_reset_discover_st +** +** Description when a SRCB finished discovery, tell all related clcb. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb) +{ + tBTA_GATTC_CB *p_cb = &bta_gattc_cb; + UINT8 i; + + for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++) + { + if (p_cb->clcb[i].p_srcb == p_srcb) + { + bta_gattc_sm_execute(&p_cb->clcb[i], BTA_GATTC_DISCOVER_CMPL_EVT, NULL); + } + } +} +/******************************************************************************* +** +** Function bta_gattc_set_discover_st +** +** Description when a SRCB start discovery, tell all related clcb and set +** the state. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_set_discover_st(tBTA_GATTC_SERV *p_srcb) +{ + tBTA_GATTC_CB *p_cb = &bta_gattc_cb; + UINT8 i; + +#if BLE_INCLUDED == TRUE + L2CA_EnableUpdateBleConnParams(p_srcb->server_bda, FALSE); +#endif + for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++) + { + if (p_cb->clcb[i].p_srcb == p_srcb) + { + p_cb->clcb[i].state = BTA_GATTC_DISCOVER_ST; + } + } +} +/******************************************************************************* +** +** Function bta_gattc_start_discover +** +** Description Start a discovery on server. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + /* pending operation, wait until it finishes */ + + APPL_TRACE_DEBUG1("bta_gattc_start_discover conn_id=%d",p_clcb->bta_conn_id); + if (p_clcb->p_q_cmd != NULL && p_clcb->auto_update == BTA_GATTC_NO_SCHEDULE && + p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) + { + p_clcb->auto_update = BTA_GATTC_DISC_WAITING; + p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */ + } + else /* no pending operation, start discovery right away */ + { + p_clcb->auto_update = BTA_GATTC_NO_SCHEDULE; + + if (p_clcb->p_srcb != NULL) + { + /* clear the service change mask */ + p_clcb->p_srcb->srvc_hdl_chg = FALSE; + p_clcb->p_srcb->update_count = 0; + + /* set all srcb related clcb into discovery ST */ + bta_gattc_set_discover_st(p_clcb->p_srcb); + + if ( bta_gattc_init_cache(p_clcb->p_srcb) || + bta_gattc_discover_pri_service(p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL) != BTA_GATT_OK) + { + APPL_TRACE_ERROR0("discovery on server failed"); + bta_gattc_reset_discover_st(p_clcb->p_srcb); + } + } + else + { + APPL_TRACE_ERROR0("unknown device, can not start discovery"); + } + } +} +/******************************************************************************* +** +** Function bta_gattc_disc_cmpl +** +** Description discovery on server is finished +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATTC_DATA *p_q_cmd = p_clcb->p_q_cmd; + APPL_TRACE_DEBUG1("bta_gattc_disc_cmpl conn_id=%d",p_clcb->bta_conn_id); + +#if BLE_INCLUDED == TRUE + L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE); +#endif + p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE; + + /* release pending attribute list buffer */ + utl_freebuf((void **)&p_clcb->p_srcb->p_srvc_list); + + /* get any queued command to proceed */ + if (p_q_cmd != NULL) + { + p_clcb->p_q_cmd = NULL; + + bta_gattc_sm_execute(p_clcb, p_q_cmd->hdr.event, p_q_cmd); + + utl_freebuf((void **)&p_q_cmd); + + } +} +/******************************************************************************* +** +** Function bta_gattc_read +** +** Description Read an attribute +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + UINT16 handle = 0; + tGATT_READ_PARAM read_param; + tBTA_GATTC_OP_CMPL op_cmpl; + + memset (&read_param, 0 ,sizeof(tGATT_READ_PARAM)); + memset (&op_cmpl, 0 ,sizeof(tBTA_GATTC_OP_CMPL)); + + if (bta_gattc_enqueue(p_clcb, p_data)) + { + if ((handle = bta_gattc_id2handle(p_clcb->p_srcb, + &p_data->api_read.srvc_id, + &p_data->api_read.char_id, + p_data->api_read.descr_type)) == 0) + { + op_cmpl.status = BTA_GATT_ERROR; + } + else + { + read_param.by_handle.handle = handle; + read_param.by_handle.auth_req = p_data->api_read.auth_req; + + op_cmpl.status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_HANDLE, &read_param); + } + + /* read fail */ + if (op_cmpl.status != BTA_GATT_OK) + { + op_cmpl.op_code = GATTC_OPTYPE_READ; + op_cmpl.p_cmpl = NULL; + + bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + } + } +} +/******************************************************************************* +** +** Function bta_gattc_read_multi +** +** Description read multiple +** +** Returns None. +*********************************************************************************/ +void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + UINT16 i, handle; + tBTA_GATT_STATUS status = BTA_GATT_OK; + tGATT_READ_PARAM read_param; + tBTA_GATTC_OP_CMPL op_cmpl; + tBTA_GATTC_ATTR_ID *p_id; + tBT_UUID dummy_uuid; + + if (bta_gattc_enqueue(p_clcb, p_data)) + { + memset(&dummy_uuid, 0, sizeof(tBT_UUID)); + memset(&read_param, 0, sizeof(tGATT_READ_PARAM)); + + p_id = p_data->api_read_multi.p_id_list; + + for (i = 0; i < p_data->api_read_multi.num_attr && p_id; i ++, p_id ++) + { + handle = 0; + + if (p_id->id_type == BTA_GATT_TYPE_CHAR) + { + handle = bta_gattc_id2handle(p_clcb->p_srcb, + &p_id->id_value.char_id.srvc_id, + &p_id->id_value.char_id.char_id, + dummy_uuid); + } + else if (p_id->id_type == BTA_GATT_TYPE_CHAR_DESCR) + { + handle = bta_gattc_id2handle(p_clcb->p_srcb, + &p_id->id_value.char_descr_id.char_id.srvc_id, + &p_id->id_value.char_descr_id.char_id.char_id, + p_id->id_value.char_descr_id.descr_type); + } + else + { + APPL_TRACE_ERROR1("invalud ID type: %d", p_id->id_type); + } + + if (handle == 0) + { + status = BTA_GATT_ERROR; + break; + } + } + if (status == BTA_GATT_OK) + { + read_param.read_multiple.num_handles = p_data->api_read_multi.num_attr; + read_param.read_multiple.auth_req = p_data->api_read_multi.auth_req; + + status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_MULTIPLE, &read_param); + } + + /* read fail */ + if (status != BTA_GATT_OK) + { + memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL)); + + op_cmpl.status = status; + op_cmpl.op_code = GATTC_OPTYPE_READ; + op_cmpl.p_cmpl = NULL; + + bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + } + } +} +/******************************************************************************* +** +** Function bta_gattc_write +** +** Description Write an attribute +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + UINT16 handle = 0; + tGATT_VALUE attr = {0}; + tBTA_GATTC_OP_CMPL op_cmpl; + tBTA_GATT_STATUS status = BTA_GATT_OK; + + if (bta_gattc_enqueue(p_clcb, p_data)) + { + if ((handle = bta_gattc_id2handle(p_clcb->p_srcb, + &p_data->api_write.srvc_id, + &p_data->api_write.char_id, + p_data->api_write.descr_type)) == 0) + { + status = BTA_GATT_ERROR; + } + else + { + attr.handle= handle; + attr.offset = p_data->api_write.offset; + attr.len = p_data->api_write.len; + attr.auth_req = p_data->api_write.auth_req; + + if (p_data->api_write.p_value) + memcpy(attr.value, p_data->api_write.p_value, p_data->api_write.len); + + status = GATTC_Write(p_clcb->bta_conn_id, p_data->api_write.write_type, &attr); + } + + /* write fail */ + if (status != BTA_GATT_OK) + { + memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL)); + + op_cmpl.status = status; + op_cmpl.op_code = GATTC_OPTYPE_WRITE; + op_cmpl.p_cmpl = NULL; + + bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + } + } +} +/******************************************************************************* +** +** Function bta_gattc_execute +** +** Description send execute write +** +** Returns None. +*********************************************************************************/ +void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATTC_OP_CMPL op_cmpl; + tBTA_GATT_STATUS status; + + if (bta_gattc_enqueue(p_clcb, p_data)) + { + status = GATTC_ExecuteWrite(p_clcb->bta_conn_id, p_data->api_exec.is_execute); + + if (status != BTA_GATT_OK) + { + memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL)); + + op_cmpl.status = status; + op_cmpl.op_code = GATTC_OPTYPE_EXE_WRITE; + op_cmpl.p_cmpl = NULL; + + bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl); + } + } +} + +/******************************************************************************* +** +** Function bta_gattc_confirm +** +** Description send handle value confirmation +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + UINT16 handle; + tBT_UUID null_uuid = {0}; + + if ((handle = bta_gattc_id2handle(p_clcb->p_srcb, + &p_data->api_confirm.srvc_id, + &p_data->api_confirm.char_id, + null_uuid)) == 0) + { + APPL_TRACE_ERROR0("Can not map service/char ID into valid handle"); + } + else + { + if (GATTC_SendHandleValueConfirm(p_data->api_confirm.hdr.layer_specific, handle) + != GATT_SUCCESS) + { + APPL_TRACE_ERROR1("bta_gattc_confirm to handle [0x%04x] failed", handle); + } + } +} +/******************************************************************************* +** +** Function bta_gattc_read_cmpl +** +** Description read complete +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) +{ + UINT8 event; + tBTA_GATTC cb_data; + tBTA_GATT_READ_VAL read_value; + + memset(&cb_data, 0, sizeof(tBTA_GATTC)); + memset(&read_value, 0, sizeof(tBTA_GATT_READ_VAL)); + + cb_data.read.status = p_data->status; + + if (p_data->p_cmpl != NULL && p_data->status == BTA_GATT_OK) + { + if (bta_gattc_handle2id(p_clcb->p_srcb, + p_data->p_cmpl->att_value.handle, + &cb_data.read.srvc_id, + &cb_data.read.char_id, + &cb_data.read.descr_type) == FALSE) + { + cb_data.read.status = BTA_GATT_INTERNAL_ERROR; + APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", p_data->p_cmpl->att_value.handle); + } + else + { + cb_data.read.status = bta_gattc_pack_read_cb_data(p_clcb->p_srcb, + cb_data.read.descr_type, + &p_data->p_cmpl->att_value, + &read_value); + cb_data.read.p_value = &read_value; + } + } + else + { + cb_data.read.srvc_id = p_clcb->p_q_cmd->api_read.srvc_id; + cb_data.read.char_id = p_clcb->p_q_cmd->api_read.char_id; + cb_data.read.descr_type = p_clcb->p_q_cmd->api_read.descr_type; + } + + event = (p_clcb->p_q_cmd->api_read.descr_type.len == 0) ? BTA_GATTC_READ_CHAR_EVT: BTA_GATTC_READ_DESCR_EVT; + cb_data.read.conn_id = p_clcb->bta_conn_id; + + utl_freebuf((void **)&p_clcb->p_q_cmd); + /* read complete, callback */ + ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); + +} +/******************************************************************************* +** +** Function bta_gattc_write_cmpl +** +** Description read complete +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) +{ + tBTA_GATTC cb_data = {0}; + UINT8 event; + + cb_data.write.status = p_data->status; + + if (p_data->p_cmpl != NULL) + { + bta_gattc_handle2id(p_clcb->p_srcb, p_data->p_cmpl->handle, + &cb_data.write.srvc_id, &cb_data.write.char_id, + &cb_data.write.descr_type); + } + else + { + cb_data.write.srvc_id = p_clcb->p_q_cmd->api_write.srvc_id; + cb_data.write.char_id = p_clcb->p_q_cmd->api_write.char_id; + cb_data.write.descr_type = p_clcb->p_q_cmd->api_write.descr_type; + } + + if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT && + p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE) + + event = BTA_GATTC_PREP_WRITE_EVT; + + else if (p_clcb->p_q_cmd->api_write.descr_type.len == 0) + + event = BTA_GATTC_WRITE_CHAR_EVT; + + else + event = BTA_GATTC_WRITE_DESCR_EVT; + + utl_freebuf((void **)&p_clcb->p_q_cmd); + cb_data.write.conn_id = p_clcb->bta_conn_id; + /* write complete, callback */ + ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data); + +} +/******************************************************************************* +** +** Function bta_gattc_exec_cmpl +** +** Description execute write complete +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data) +{ + tBTA_GATTC cb_data; + + utl_freebuf((void **)&p_clcb->p_q_cmd); + + p_clcb->status = BTA_GATT_OK; + + /* execute complete, callback */ + cb_data.exec_cmpl.conn_id = p_clcb->bta_conn_id; + cb_data.exec_cmpl.status = p_data->status; + + ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_EXEC_EVT, &cb_data); + +} + + +/******************************************************************************* +** +** Function bta_gattc_op_cmpl +** +** Description operation completed. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + UINT8 op = (UINT8)p_data->op_cmpl.op_code; + UINT8 mapped_op = 0; + + APPL_TRACE_DEBUG1("bta_gattc_op_cmpl op = %d", op); + + if (op == GATTC_OPTYPE_INDICATION || op == GATTC_OPTYPE_NOTIFICATION) + { + APPL_TRACE_ERROR0("unexpected operation, ignored"); + } + else if (op >= GATTC_OPTYPE_READ) + { + if (p_clcb->p_q_cmd == NULL) + { + APPL_TRACE_ERROR0("No pending command"); + return; + } + if (p_clcb->p_q_cmd->hdr.event != bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ]) + { + mapped_op = p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT + GATTC_OPTYPE_READ; + if ( mapped_op > GATTC_OPTYPE_INDICATION) mapped_op = 0; + +#if (BT_TRACE_VERBOSE == TRUE) + APPL_TRACE_ERROR3("expect op:(%s :0x%04x), receive unexpected operation (%s).", + bta_gattc_op_code_name[mapped_op] , p_clcb->p_q_cmd->hdr.event, + bta_gattc_op_code_name[op]); +#else + APPL_TRACE_ERROR3("expect op:(%u :0x%04x), receive unexpected operation (%u).", + mapped_op , p_clcb->p_q_cmd->hdr.event, op); +#endif + return; + } + + /* service handle change void the response, discard it */ + if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING) + { + p_clcb->auto_update = BTA_GATTC_REQ_WAITING; + bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); + } + else if (op == GATTC_OPTYPE_READ) + bta_gattc_read_cmpl(p_clcb, &p_data->op_cmpl); + + else if (op == GATTC_OPTYPE_WRITE) + bta_gattc_write_cmpl(p_clcb, &p_data->op_cmpl); + + else if (op == GATTC_OPTYPE_EXE_WRITE) + bta_gattc_exec_cmpl(p_clcb, &p_data->op_cmpl); + /* + else if (op == GATTC_OPTYPE_CONFIG) // API to be added + { + } + */ + } +} +/******************************************************************************* +** +** Function bta_gattc_op_cmpl +** +** Description operation completed. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + /* receive op complete when discovery is started, ignore the response, + and wait for discovery finish and resent */ + APPL_TRACE_DEBUG1("bta_gattc_ignore_op_cmpl op = %d", p_data->hdr.layer_specific); + +} +/******************************************************************************* +** +** Function bta_gattc_search +** +** Description start a search in the local server cache +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + tBTA_GATT_STATUS status = GATT_INTERNAL_ERROR; + tBTA_GATTC cb_data; + APPL_TRACE_DEBUG1("bta_gattc_search conn_id=%d",p_clcb->bta_conn_id); + if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache) + { + status = BTA_GATT_OK; + /* search the local cache of a server device */ + bta_gattc_search_service(p_clcb, p_data->api_search.srvc_uuid); + } + cb_data.search_cmpl.status = status; + cb_data.search_cmpl.conn_id = p_clcb->bta_conn_id; + + /* end of search or no server cache available */ + ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_CMPL_EVT, &cb_data); +} +/******************************************************************************* +** +** Function bta_gattc_q_cmd +** +** Description enqueue a command into control block, usually because discovery +** operation is busy. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + bta_gattc_enqueue(p_clcb, p_data); +} +/******************************************************************************* +** +** Function bta_gattc_cache_open +** +** Description open a NV cache for loading +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + bta_gattc_set_discover_st(p_clcb->p_srcb); + + APPL_TRACE_DEBUG1("bta_gattc_cache_open conn_id=%d",p_clcb->bta_conn_id); + bta_gattc_co_cache_open(p_clcb->p_srcb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT, + p_clcb->bta_conn_id, FALSE); +} +/******************************************************************************* +** +** Function bta_gattc_start_load +** +** Description start cache loading by sending callout open cache +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + APPL_TRACE_DEBUG2("bta_gattc_ci_open conn_id=%d server state=%d" , + p_clcb->bta_conn_id, p_clcb->p_srcb->state); + if (p_clcb->p_srcb->state == BTA_GATTC_SERV_LOAD) + { + if (p_data->ci_open.status == BTA_GATT_OK) + { + p_clcb->p_srcb->attr_index = 0; + bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda, + BTA_GATTC_CI_CACHE_LOAD_EVT, + p_clcb->p_srcb->attr_index, + p_clcb->bta_conn_id); + } + else + { + /* cache open failure, start discovery */ + bta_gattc_start_discover(p_clcb, NULL); + } + } + if (p_clcb->p_srcb->state == BTA_GATTC_SERV_SAVE) + { + if (p_data->ci_open.status == BTA_GATT_OK) + { + if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id)) + { + p_data->ci_open.status = BTA_GATT_ERROR; + } + } + if (p_data->ci_open.status != BTA_GATT_OK) + { + p_clcb->p_srcb->attr_index = 0; + bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, p_clcb->bta_conn_id); + bta_gattc_reset_discover_st(p_clcb->p_srcb); + + } + } +} +/******************************************************************************* +** +** Function bta_gattc_ci_load +** +** Description cache loading received. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + + APPL_TRACE_DEBUG2("bta_gattc_ci_load conn_id=%d load status=%d" , + p_clcb->bta_conn_id, p_data->ci_load.status ); + bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0); + + if ((p_data->ci_load.status == BTA_GATT_OK || + p_data->ci_load.status == BTA_GATT_MORE) && + p_data->ci_load.num_attr > 0) + { + bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr, p_data->ci_load.attr, p_clcb->p_srcb->attr_index); + + if (p_data->ci_load.status == BTA_GATT_OK) + { + p_clcb->p_srcb->attr_index = 0; + bta_gattc_reset_discover_st(p_clcb->p_srcb); + + } + else /* load more */ + { + p_clcb->p_srcb->attr_index += p_data->ci_load.num_attr; + + bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda, + BTA_GATTC_CI_CACHE_LOAD_EVT, + p_clcb->p_srcb->attr_index, + p_clcb->bta_conn_id); + } + } + else + { + p_clcb->p_srcb->attr_index = 0; + /* cache open failure, start discovery */ + bta_gattc_start_discover(p_clcb, NULL); + } +} +/******************************************************************************* +** +** Function bta_gattc_ci_load +** +** Description cache loading received. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + APPL_TRACE_DEBUG1("bta_gattc_ci_save conn_id=%d " , + p_clcb->bta_conn_id ); + + if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id)) + { + p_clcb->p_srcb->attr_index = 0; + bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0); + bta_gattc_reset_discover_st(p_clcb->p_srcb); + } +} + +/******************************************************************************* +** +** Function bta_gattc_fail +** +** Description report API call failure back to apps +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data) +{ + if (p_clcb->status == BTA_GATT_OK) + { + APPL_TRACE_ERROR1("operation not supported at current state [%d]", p_clcb->state); + } +} +/******************************************************************************* +** +** Function bta_gattc_conn_cback +** bta_gattc_cmpl_cback +** +** Description callback functions to GATT client stack. +** +** Returns void +** +*******************************************************************************/ +static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id, + BOOLEAN connected, tGATT_DISCONN_REASON reason) +{ + BT_HDR *p_buf; + tBTA_GATTC_CLCB *p_clcb = NULL; + + APPL_TRACE_DEBUG4("bta_gattc_conn_cback: cif = %d connected = %d conn_id = %d reaosn = 0x%04x", + gattc_if, connected, conn_id, reason); + + if (connected) + { + /* outgoing connection : locate a logic channel */ + if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda)) == NULL) + { + +#if BLE_INCLUDED == TRUE + /* for a background connection */ + if (L2CA_GetBleConnRole(bda)== HCI_ROLE_MASTER && + bta_gattc_check_bg_conn(gattc_if, bda)) + { + /* allocate a new channel */ + p_clcb = bta_gattc_clcb_alloc(gattc_if, bda); + } +#endif + } + if (p_clcb != NULL) + { + p_clcb->bta_conn_id = conn_id; + + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->event = BTA_GATTC_INT_CONN_EVT; + p_buf->layer_specific = conn_id; + + bta_sys_sendmsg(p_buf); + } + } + } + else + { + /* connection attempt timeout, send connection callback event */ + if (reason == GATT_CONN_CANCEL ) + { + p_clcb = bta_gattc_clcb_alloc(gattc_if, bda); + p_clcb->bta_conn_id = conn_id; + } + if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) != NULL) + { + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->event = BTA_GATTC_INT_DISCONN_EVT; + p_buf->layer_specific = conn_id; + p_clcb->reason = reason; + + bta_sys_sendmsg(p_buf); + } + } + else + { + APPL_TRACE_DEBUG1(" connection ID: [%d] not used by BTA", conn_id); + } + } +} +/******************************************************************************* +** +** Function bta_gattc_process_srvc_chg_ind +** +** Description process service change indication. +** +** Returns None. +** +*******************************************************************************/ +BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id, + tBTA_GATTC_RCB *p_clrcb, + tBTA_GATTC_SERV *p_srcb, + tBTA_GATTC_CLCB *p_clcb, + tBTA_GATTC_NOTIFY *p_notify, + UINT16 handle) +{ + tBT_UUID gattp_uuid, srvc_chg_uuid; + BOOLEAN processed = FALSE; + UINT8 i; + + gattp_uuid.len = 2; + gattp_uuid.uu.uuid16 = UUID_SERVCLASS_GATT_SERVER; + + srvc_chg_uuid.len = 2; + srvc_chg_uuid.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD; + + if (bta_gattc_uuid_compare(p_notify->char_id.srvc_id.id.uuid, gattp_uuid, TRUE) && + bta_gattc_uuid_compare(p_notify->char_id.char_id.uuid, srvc_chg_uuid, TRUE)) + { + processed = TRUE; + /* mark service handle change pending */ + p_srcb->srvc_hdl_chg = TRUE; + /* clear up all notification/indication registration */ + bta_gattc_clear_notif_registration(conn_id); + /* service change indication all received, do discovery update */ + if ( ++ p_srcb->update_count == bta_gattc_num_reg_app()) + { + /* not an opened connection; or connection busy */ + /* search for first available clcb and start discovery */ + if (p_clcb == NULL || (p_clcb && p_clcb->p_q_cmd != NULL)) + { + for (i = 0 ; i < BTA_GATTC_CLCB_MAX; i ++) + { + if (bta_gattc_cb.clcb[i].in_use && + bta_gattc_cb.clcb[i].p_srcb == p_srcb && + bta_gattc_cb.clcb[i].p_q_cmd == NULL) + { + p_clcb = &bta_gattc_cb.clcb[i]; + break; + } + } + } + /* send confirmation here if this is an indication, it should always be */ + GATTC_SendHandleValueConfirm(conn_id, handle); + + /* if connection available, refresh cache by doing discovery now */ + if (p_clcb != NULL) + bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); + } + /* notify applicationf or service change */ + if (p_clrcb->p_cback != NULL) + { + APPL_TRACE_ERROR0("bta_gattc_process_srvc_chg_ind 2"); + (* p_clrcb->p_cback)(BTA_GATTC_SRVC_CHG_EVT, (tBTA_GATTC *)p_srcb->server_bda); + } + + } + + return processed; + +} +/******************************************************************************* +** +** Function bta_gattc_proc_other_indication +** +** Description process all non-service change indication/notification. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_proc_other_indication(tBTA_GATTC_CLCB *p_clcb, UINT8 op, + tGATT_CL_COMPLETE *p_data, + tBTA_GATTC_NOTIFY *p_notify) +{ + APPL_TRACE_DEBUG2("bta_gattc_proc_other_indication check \ + p_data->att_value.handle=%d p_data->handle=%d", + p_data->att_value.handle, p_data->handle); + APPL_TRACE_DEBUG1("is_notify", p_notify->is_notify); + + p_notify->is_notify = (op == GATTC_OPTYPE_INDICATION) ? FALSE : TRUE; + p_notify->len = p_data->att_value.len; + bdcpy(p_notify->bda, p_clcb->bda); + memcpy(p_notify->value, p_data->att_value.value, p_data->att_value.len); + p_notify->conn_id = p_clcb->bta_conn_id; + + if (p_clcb->p_rcb->p_cback) + (*p_clcb->p_rcb->p_cback)(BTA_GATTC_NOTIF_EVT, (tBTA_GATTC *)p_notify); + +} +/******************************************************************************* +** +** Function bta_gattc_process_indicate +** +** Description process indication/notification. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPLETE *p_data) +{ + UINT16 handle = p_data->att_value.handle; + tBTA_GATTC_CLCB *p_clcb ; + tBTA_GATTC_RCB *p_clrcb = NULL; + tBTA_GATTC_SERV *p_srcb = NULL; + tBTA_GATTC_NOTIFY notify; + BD_ADDR remote_bda; + tBTA_GATTC_IF gatt_if; + + if (!GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda)) + { + APPL_TRACE_ERROR0("indication/notif for unknown app"); + return; + } + + if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) == NULL) + { + APPL_TRACE_ERROR0("indication/notif for unregistered app"); + return; + } + + if ((p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL) + { + APPL_TRACE_ERROR0("indication/notif for unknown device, ignore"); + return; + } + + p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); + + if (bta_gattc_handle2id(p_srcb, handle, + ¬ify.char_id.srvc_id, + ¬ify.char_id.char_id, + ¬ify.descr_type)) + { + /* if non-service change indication/notification, forward to application */ + if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, ¬ify, handle)) + { + /* if app registered for the notification */ + if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, ¬ify)) + { + /* connection not open yet */ + if (p_clcb == NULL) + { + if ((p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda)) != NULL) + { + p_clcb->bta_conn_id = conn_id; + + /* send connection event */ + bta_gattc_send_open_cback(p_clrcb, + BTA_GATT_OK, + remote_bda, + conn_id); + } + else + { + APPL_TRACE_ERROR0("No resources"); + } + } + + if (p_clcb != NULL) + bta_gattc_proc_other_indication(p_clcb, op, p_data, ¬ify); + } + /* no one intersted and need ack? */ + else if (op == GATTC_OPTYPE_INDICATION) + { + APPL_TRACE_DEBUG0("no one interested, ack now"); + GATTC_SendHandleValueConfirm(conn_id, handle); + } + } + } + else + { + APPL_TRACE_ERROR1("Indi/Notif for Unknown handle[0x%04x], can not find in local cache.", handle); + } +} + +/******************************************************************************* +** +** Function bta_gattc_cmpl_cback +** +** Description client operation complete callback register with BTE GATT. +** +** Returns None. +** +*******************************************************************************/ +static void bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, + tGATT_CL_COMPLETE *p_data) +{ + tBTA_GATTC_CLCB *p_clcb ; + tBTA_GATTC_OP_CMPL *p_buf; + UINT16 len = sizeof(tBTA_GATTC_OP_CMPL) + sizeof(tGATT_CL_COMPLETE); + + APPL_TRACE_DEBUG3("bta_gattc_cmpl_cback: conn_id = %d op = %d status = %d", + conn_id, op, status); + + /* notification and indication processed right away */ + if (op == GATTC_OPTYPE_NOTIFICATION || op == GATTC_OPTYPE_INDICATION) + { + bta_gattc_process_indicate(conn_id, op, p_data); + return; + } + /* for all other operation, not expected if w/o connection */ + else if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) == NULL) + { + APPL_TRACE_ERROR1("bta_gattc_cmpl_cback unknown conn_id = %d, ignore data", conn_id); + return; + } + + + if ((p_buf = (tBTA_GATTC_OP_CMPL *) GKI_getbuf(len)) != NULL) + { + memset(p_buf, 0, len); + p_buf->hdr.event = BTA_GATTC_OP_CMPL_EVT; + p_buf->hdr.layer_specific = conn_id; + p_buf->status = status; + p_buf->op_code = op; + + if (p_data != NULL) + { + p_buf->p_cmpl = (tGATT_CL_COMPLETE *)(p_buf + 1); + memcpy(p_buf->p_cmpl, p_data, sizeof(tGATT_CL_COMPLETE)); + } + + bta_sys_sendmsg(p_buf); + } + + return; +} +#endif /* BTA_GATT_INCLUDED */ diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c new file mode 100644 index 0000000..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 +#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 +#include "utl.h" +#include "gki.h" +#include "bta_sys.h" +#include "sdp_api.h" +#include "sdpdefs.h" +#include "bta_gattc_int.h" +#include "btm_api.h" + +static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb); +static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb); + +#define BTA_GATT_SDP_DB_SIZE 750 + +/***************************************************************************** +** Constants +*****************************************************************************/ + +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) +static char *bta_gattc_attr_type[] = +{ + "I", /* Included Service */ + "C", /* Characteristic */ + "D" /* Characteristic Descriptor */ +}; +/* utility functions */ + +/******************************************************************************* +** +** Function bta_gattc_display_cache_server +** +** Description debug function to display the server cache. +** +** Returns none. +** +*******************************************************************************/ +static void bta_gattc_display_cache_server(tBTA_GATTC_CACHE *p_cache) +{ + UINT8 i = 0, j; + tBTA_GATTC_CACHE *p_cur_srvc = p_cache; + tBTA_GATTC_CACHE_ATTR *p_attr; + + APPL_TRACE_ERROR0("<================Start Server Cache =============>"); + + while (p_cur_srvc) + { + APPL_TRACE_ERROR6("Service[%d]: handle[%d ~ %d] %s[0x%04x] inst[%d]", + i, p_cur_srvc->s_handle, p_cur_srvc->e_handle, + ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"), + p_cur_srvc->service_uuid.id.uuid.uu.uuid16, + p_cur_srvc->service_uuid.id.inst_id); + i ++; + + p_attr = p_cur_srvc->p_attr; + + for (j = 0; p_attr; j ++ ) + { + APPL_TRACE_ERROR6("\t Attr[0x%04x] handle[%d] uuid[0x%04x] inst[%d] type[%s] prop[0x%1x]", + j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, + bta_gattc_attr_type[p_attr->attr_type], p_attr->property); + + p_attr = p_attr->p_next; + } + p_cur_srvc = p_cur_srvc->p_next; + } + + APPL_TRACE_ERROR0("<================End Server Cache =============>"); + APPL_TRACE_ERROR0(" "); +} + +/******************************************************************************* +** +** Function bta_gattc_display_explore_record +** +** Description debug function to display the exploration list +** +** Returns none. +** +*******************************************************************************/ +static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec) +{ + UINT8 i; + tBTA_GATTC_ATTR_REC *pp = p_rec; + + APPL_TRACE_ERROR0("<================Start Explore Queue =============>"); + for (i = 0; i < num_rec; i ++, pp ++) + { + APPL_TRACE_ERROR5("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]", + i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary); + } + APPL_TRACE_ERROR0("<================ End Explore Queue =============>"); + APPL_TRACE_ERROR0(" "); + +} +#endif /* BTA_GATT_DEBUG == TRUE */ + + +/******************************************************************************* +** +** Function bta_gattc_alloc_cache_buf +** +** Description Allocate a GKI buffer for database cache. +** +** Returns status +** +*******************************************************************************/ +BT_HDR *bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV *p_srvc_cb) +{ + BT_HDR *p_buf; + + if ((p_buf = (BT_HDR *)GKI_getpoolbuf(GATT_DB_POOL_ID)) == NULL) + { + APPL_TRACE_DEBUG0("No resources: GKI buffer allocation failed."); + utl_freebuf((void **)&p_srvc_cb->p_srvc_list); + p_srvc_cb->free_byte = 0; + } + else + { + memset(p_buf, 0, GKI_get_buf_size(p_buf)); + p_srvc_cb->p_free = (UINT8 *) p_buf; + p_srvc_cb->free_byte = GKI_get_buf_size(p_buf); + + /* link into buffer queue */ + GKI_enqueue(&p_srvc_cb->cache_buffer, p_buf); + } +#if BTA_GATT_DEBUG== TRUE + APPL_TRACE_DEBUG1("allocating new buffer: free byte = %d", p_srvc_cb->free_byte); +#endif + return p_buf; +} +/******************************************************************************* +** +** Function bta_gattc_init_cache +** +** Description Initialize the database cache and discovery related resources. +** +** Returns status +** +*******************************************************************************/ +tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb) +{ + tBTA_GATT_STATUS status = BTA_GATT_OK; + + while (p_srvc_cb->cache_buffer.p_first) + GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer)); + + utl_freebuf((void **)&p_srvc_cb->p_srvc_list); + + if ((p_srvc_cb->p_srvc_list = (tBTA_GATTC_ATTR_REC*)GKI_getbuf(BTA_GATTC_ATTR_LIST_SIZE)) == NULL) + { + APPL_TRACE_DEBUG0("No resources: GKI buffer allocation failed."); + status = GATT_NO_RESOURCES; + } + else + { + p_srvc_cb->total_srvc = 0; + p_srvc_cb->cur_srvc_idx = + p_srvc_cb->cur_char_idx = + p_srvc_cb->next_avail_idx = 0; + + if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) + { + status = GATT_NO_RESOURCES; + } + else + { + p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL; + } + } + + return status; +} +/******************************************************************************* +** +** Function bta_gattc_get_srvc_inst_id +** +** Description get service instance number +** +** Returns instance ID of the service. +** +*******************************************************************************/ +static UINT8 bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID uuid) +{ + UINT8 i = 0, inst = 0; + tBTA_GATTC_ATTR_REC *p_srvc_rec; + + for (i = 0; i < p_srvc_cb->total_srvc; i ++) + /* + for (; i < p_srvc_cb->cur_srvc_idx; i ++)*/ + { + p_srvc_rec = p_srvc_cb->p_srvc_list + i; + + if (bta_gattc_uuid_compare(p_srvc_rec->uuid, uuid, TRUE)) + inst ++; + } + return inst ; +} +/******************************************************************************* +** +** Function bta_gattc_get_char_inst_id +** +** Description get characteristic instance number +** +** Returns characteristic instance ID. +** +*******************************************************************************/ +static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID uuid) +{ + UINT8 inst = 0; + tBTA_GATTC_CACHE_ATTR *p_attr; + tBT_UUID attr_uuid; + + p_attr = p_service_cache->p_attr; + + while (p_attr) + { + bta_gattc_pack_attr_uuid(p_attr, &attr_uuid); + + if (bta_gattc_uuid_compare(attr_uuid, uuid, TRUE)) + inst ++; + + p_attr = p_attr->p_next; + } + return inst ; +} + +/******************************************************************************* +** +** Function bta_gattc_add_srvc_to_cache +** +** Description Add a service into database cache. +** +** Returns status +** +*******************************************************************************/ +static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb, + UINT16 s_handle, UINT16 e_handle, + tBT_UUID *p_uuid, + BOOLEAN is_primary, UINT8 srvc_inst) +{ + tBTA_GATTC_CACHE *p_new_srvc = NULL; + tBTA_GATT_STATUS status = BTA_GATT_OK; + +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG0("Add a service into Service"); + APPL_TRACE_DEBUG2("free byte = %d, req %d bytes.", p_srvc_cb->free_byte, sizeof(tBTA_GATTC_CACHE)) +#endif + + if (p_srvc_cb->free_byte < sizeof(tBTA_GATTC_CACHE)) + { + if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) + return GATT_NO_RESOURCES; + } + + p_new_srvc = (tBTA_GATTC_CACHE *)p_srvc_cb->p_free; + /* update service information */ + p_new_srvc->s_handle = s_handle; + p_new_srvc->e_handle = e_handle; + p_new_srvc->service_uuid.is_primary = is_primary; + memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID)); + p_new_srvc->service_uuid.id.inst_id = srvc_inst; + p_new_srvc->p_next = NULL; + + if (p_srvc_cb->p_cur_srvc != NULL) + p_srvc_cb->p_cur_srvc->p_next = p_new_srvc; + p_srvc_cb->p_cur_srvc = p_new_srvc; + + /* first service */ + if (p_srvc_cb->p_srvc_cache == NULL) + p_srvc_cb->p_srvc_cache = p_new_srvc; + + /* update buffer managament info */ + p_srvc_cb->p_free += sizeof(tBTA_GATTC_CACHE); + p_srvc_cb->free_byte -= sizeof(tBTA_GATTC_CACHE); + + +#if 0 +//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache); +#endif + return status; +} +/******************************************************************************* +** +** Function bta_gattc_add_attr_to_cache +** +** Description Add an attribute into database cache buffer. +** +** Returns status +** +*******************************************************************************/ +static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb, + UINT16 handle, + tBT_UUID *p_uuid, + UINT8 property, + tBTA_GATTC_ATTR_TYPE type) +{ + tBTA_GATTC_CACHE_ATTR *p_attr; + tBTA_GATT_STATUS status = BTA_GATT_OK; + UINT16 len = sizeof(tBTA_GATTC_CACHE_ATTR) + p_uuid->len; + UINT8 *pp; + +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG1("bta_gattc_add_attr_to_cache: Add a [%s] into Service", bta_gattc_attr_type[type]); + APPL_TRACE_DEBUG4("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type); + APPL_TRACE_DEBUG2("free byte = %d, req %d bytes.", p_srvc_cb->free_byte, len); +#endif + + if (p_srvc_cb->free_byte < len) + { + if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) + return GATT_NO_RESOURCES; + } + + p_attr = (tBTA_GATTC_CACHE_ATTR *)p_srvc_cb->p_free; + + p_attr->attr_handle = handle; + p_attr->attr_type = type; + p_attr->property = property; + p_attr->uuid_len = p_uuid->len; + p_attr->p_uuid = (tBTA_GATTC_UUID *)(p_attr + 1); + p_attr->p_next = NULL; + + pp = (UINT8 *)p_attr->p_uuid; + + if (p_uuid->len == LEN_UUID_16) + { + UINT16_TO_STREAM(pp, p_uuid->uu.uuid16); + } + else if (p_uuid->len == LEN_UUID_128) + { + memcpy(pp, p_uuid->uu.uuid128, LEN_UUID_128); + } + + if (type == BTA_GATTC_ATTR_TYPE_CHAR) + p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, *p_uuid); + /* else: char descriptor, no instance ID needed */ + else /* TODO: --->> temp treat included service same as char descriptor */ + p_attr->inst_id = 0; + + /* update service information */ + p_srvc_cb->p_free += len; + p_srvc_cb->free_byte -= len; + + /* first attribute within the service, update the attribute pointer */ + if (p_srvc_cb->p_cur_srvc->p_attr == NULL) + { + p_srvc_cb->p_cur_srvc->p_attr = p_attr; + } + if (p_srvc_cb->p_cur_srvc->p_last_attr != NULL) + p_srvc_cb->p_cur_srvc->p_last_attr->p_next = p_attr; + + p_srvc_cb->p_cur_srvc->p_last_attr = p_attr; + +#if 0 +//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache); +#endif + return status; +} + +/******************************************************************************* +** +** Function bta_gattc_get_disc_range +** +** Description get discovery stating and ending handle range. +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc) +{ + tBTA_GATTC_ATTR_REC *p_rec = NULL; + + if (is_srvc) + { + p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx; + *p_s_hdl = p_rec->s_handle; + } + else + { + p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx; + *p_s_hdl = p_rec->s_handle + 1; + } + + *p_e_hdl = p_rec->e_handle; +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG2("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle); +#endif + return; +} +/******************************************************************************* +** +** Function bta_gattc_discover_pri_service +** +** Description Start primary service discovery +** +** Returns status of the operation. +** +*******************************************************************************/ +tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type) +{ +#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)) + tBT_DEVICE_TYPE dev_type; + tBLE_ADDR_TYPE addr_type; + + BTM_ReadDevInfo(p_server_cb->server_bda, &dev_type, &addr_type); + if (dev_type == BT_DEVICE_TYPE_BLE) + return bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type); + else + return bta_gattc_sdp_service_disc(conn_id, p_server_cb); +#endif + return BTA_GATT_ERROR; + +} +/******************************************************************************* +** +** Function bta_gattc_discover_procedure +** +** Description Start a particular type of discovery procedure on server. +** +** Returns status of the operation. +** +*******************************************************************************/ +tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type) +{ + tGATT_DISC_PARAM param; + BOOLEAN is_service = TRUE; + + memset(¶m, 0, sizeof(tGATT_DISC_PARAM)); + + if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID) + { + param.s_handle = 1; + param.e_handle = 0xFFFF; + } + else + { + if (disc_type == GATT_DISC_CHAR_DSCPT) + is_service = FALSE; + + bta_gattc_get_disc_range(p_server_cb, ¶m.s_handle, ¶m.e_handle, is_service); + + if (param.s_handle > param.e_handle) + { + APPL_TRACE_ERROR2("discover range invalid: [0x%04x ~ 0x%04x]", param.s_handle, param.e_handle); + + return GATT_ERROR; + } + } + return GATTC_Discover (conn_id, disc_type, ¶m); + +} +/******************************************************************************* +** +** Function bta_gattc_start_disc_include_srvc +** +** Description Start discovery for included service +** +** Returns status of the operation. +** +*******************************************************************************/ +tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) +{ + APPL_TRACE_DEBUG0("starting discovery included service"); + + return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC); +} +/******************************************************************************* +** +** Function bta_gattc_start_disc_char +** +** Description Start discovery for characteristic +** +** Returns status of the operation. +** +*******************************************************************************/ +tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) +{ + p_srvc_cb->total_char = 0; + + APPL_TRACE_DEBUG0("starting discover characteristics"); + + return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR); +} +/******************************************************************************* +** +** Function bta_gattc_start_disc_char_dscp +** +** Description Start discovery for characteristic descriptor +** +** Returns none. +** +*******************************************************************************/ +void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) +{ + APPL_TRACE_DEBUG0("starting discover characteristics descriptor"); + + if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0) + bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb); + +} +/******************************************************************************* +** +** Function bta_gattc_explore_srvc +** +** Description process the service discovery complete event +** +** Returns status +** +*******************************************************************************/ +static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) +{ + tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx; + tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); + + APPL_TRACE_DEBUG1("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx); + + p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc; + + if (p_clcb == NULL) + { + APPL_TRACE_ERROR0("unknown connection ID"); + return; + } + /* start expore a service if there is service not been explored */ + if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc) + { + /* add the first service into cache */ + if (bta_gattc_add_srvc_to_cache (p_srvc_cb, + p_rec->s_handle, + p_rec->e_handle, + &p_rec->uuid, + p_rec->is_primary, + p_rec->srvc_inst_id) == 0) + { + /* start discovering included services */ + bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb); + return; + } + } + /* no service found at all, the end of server discovery*/ + APPL_TRACE_ERROR0("No More Service found"); + +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache); +#endif + /* save cache to NV */ + p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE; + bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT, + conn_id, TRUE); + //bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL); +} +/******************************************************************************* +** +** Function bta_gattc_incl_srvc_disc_cmpl +** +** Description process the relationship discovery complete event +** +** Returns status +** +*******************************************************************************/ +static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) +{ + p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc; + + /* start discoverying characteristic */ + bta_gattc_start_disc_char(conn_id, p_srvc_cb); +} +/******************************************************************************* +** +** Function bta_gattc_char_disc_cmpl +** +** Description process the characteristic discovery complete event +** +** Returns status +** +*******************************************************************************/ +static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) +{ + tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx; + + APPL_TRACE_DEBUG1("Total %d Char found ", p_srvc_cb->total_char); + + /* if there are characteristic needs to be explored */ + if (p_srvc_cb->total_char > 0) + { + /* add the first characteristic into cache */ + bta_gattc_add_attr_to_cache (p_srvc_cb, + p_rec->s_handle, + &p_rec->uuid, + p_rec->property, + BTA_GATTC_ATTR_TYPE_CHAR); + + /* start discoverying characteristic descriptor , if failed, disc for next char*/ + bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb); + } + else /* otherwise start with next service */ + { + p_srvc_cb->cur_srvc_idx ++; + + bta_gattc_explore_srvc (conn_id, p_srvc_cb); + } +} +/******************************************************************************* +** +** Function bta_gattc_char_dscpt_disc_cmpl +** +** Description process the char descriptor discovery complete event +** +** Returns status +** +*******************************************************************************/ +static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb) +{ + tBTA_GATTC_ATTR_REC *p_rec = NULL; + + if (-- p_srvc_cb->total_char > 0) + { + p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx); + /* add the next characteristic into cache */ + bta_gattc_add_attr_to_cache (p_srvc_cb, + p_rec->s_handle, + &p_rec->uuid, + p_rec->property, + BTA_GATTC_ATTR_TYPE_CHAR); + + /* start discoverying next characteristic for char descriptor */ + bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb); + } + else + /* all characteristic has been explored, start with next service if any */ + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_ERROR0("all char has been explored"); +#endif + p_srvc_cb->cur_srvc_idx ++; + bta_gattc_explore_srvc (conn_id, p_srvc_cb); + } + +} +static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle, + UINT16 e_handle, tBT_UUID uuid) +{ + tBTA_GATTC_ATTR_REC *p_rec = NULL; + UINT8 i; + BOOLEAN exist_srvc = FALSE; + + if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) + { + APPL_TRACE_ERROR2("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle); + exist_srvc = TRUE; + } + else + { + for (i = 0; i < p_srvc_cb->next_avail_idx; i ++) + { + p_rec = p_srvc_cb->p_srvc_list + i; + + /* a new service should not have any overlap with other service handle range */ + if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle) + { + exist_srvc = TRUE; + break; + } + } + } + return exist_srvc; +} +/******************************************************************************* +** +** Function bta_gattc_add_srvc_to_list +** +** Description Add a service into explore pending list +** +** Returns status +** +*******************************************************************************/ +static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb, + UINT16 s_handle, UINT16 e_handle, + tBT_UUID uuid, BOOLEAN is_primary) +{ + tBTA_GATTC_ATTR_REC *p_rec = NULL; + tBTA_GATT_STATUS status = BTA_GATT_OK; + + if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) + { + p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx; + + p_srvc_cb->total_srvc ++; + + APPL_TRACE_DEBUG2("bta_gattc_add_srvc_to_list handle = %d, service type = 0x%04x", + s_handle, uuid.uu.uuid16); + + p_rec->s_handle = s_handle; + p_rec->e_handle = e_handle; + p_rec->is_primary = is_primary; + p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid); + memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID)); + + p_srvc_cb->next_avail_idx ++; + + } + else + { /* allocate bigger buffer ?? */ + status = GATT_DB_FULL; + + APPL_TRACE_ERROR0("char not added, no resources"); + } + return status; +} +/******************************************************************************* +** +** Function bta_gattc_add_char_to_list +** +** Description Add a characteristic into explore pending list +** +** Returns status +** +*******************************************************************************/ +static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb, + UINT16 decl_handle, UINT16 value_handle, + tBT_UUID uuid, UINT8 property) +{ + tBTA_GATTC_ATTR_REC *p_rec = NULL; + tBTA_GATT_STATUS status = BTA_GATT_OK; + + if (p_srvc_cb->p_srvc_list == NULL) + { + APPL_TRACE_ERROR0("No service available, unexpected char discovery result"); + status = BTA_GATT_INTERNAL_ERROR; + } + else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR) + { + + p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx; + + p_srvc_cb->total_char ++; + + p_rec->s_handle = value_handle; + p_rec->property = property; + p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle; + memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID)); + + /* update the endind handle of pervious characteristic if available */ + if (p_srvc_cb->total_char > 1) + { + p_rec -= 1; + p_rec->e_handle = decl_handle - 1; + } + p_srvc_cb->next_avail_idx ++; + } + else + { + APPL_TRACE_ERROR0("char not added, no resources"); + /* allocate bigger buffer ?? */ + status = BTA_GATT_DB_FULL; + } + return status; + +} +/******************************************************************************* +** +** Function bta_gattc_sdp_callback +** +** Description Process the discovery result from sdp +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_sdp_callback (UINT16 sdp_status) +{ + tSDP_DISC_REC *p_sdp_rec = NULL; + tBT_UUID service_uuid; + tSDP_PROTOCOL_ELEM pe; + UINT16 start_handle = 0, end_handle = 0; + tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_scb_by_cid(bta_gattc_cb.sdp_conn_id); + + if(((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL) + { + do + { + /* find a service record, report it */ + p_sdp_rec = SDP_FindServiceInDb(bta_gattc_cb.p_sdp_db, + 0, p_sdp_rec); + if (p_sdp_rec) + { + if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) + { + + if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe)) + { + start_handle = (UINT16) pe.params[0]; + end_handle = (UINT16) pe.params[1]; + +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_EVENT3("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]", + service_uuid.uu.uuid16, start_handle, end_handle); +#endif + + if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle) && + p_srvc_cb != NULL) + { + /* discover services result, add services into a service list */ + bta_gattc_add_srvc_to_list(p_srvc_cb, + start_handle, + end_handle, + service_uuid, + TRUE); + } + else + { + APPL_TRACE_ERROR2("invalid start_handle = %d end_handle = %d", start_handle, end_handle); + } + } + + + } + } + } while (p_sdp_rec); + } + + if ( p_srvc_cb != NULL) + /* start discover primary service */ + bta_gattc_explore_srvc(bta_gattc_cb.sdp_conn_id, p_srvc_cb); + else + { + APPL_TRACE_ERROR0("GATT service discovery is done on unknown connection"); + } + + GKI_freebuf(bta_gattc_cb.p_sdp_db); + bta_gattc_cb.p_sdp_db = NULL; + bta_gattc_cb.sdp_conn_id = 0; +} +/******************************************************************************* +** +** Function bta_gattc_sdp_service_disc +** +** Description Start DSP Service Discovert +** +** Returns void +** +*******************************************************************************/ +static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb) +{ + tSDP_UUID uuid; + UINT16 num_attrs = 2; + UINT16 attr_list[2]; + tBTA_GATT_STATUS status = BTA_GATT_ERROR; + + memset (&uuid, 0, sizeof(tSDP_UUID)); + + uuid.len = LEN_UUID_16; + uuid.uu.uuid16 = UUID_PROTOCOL_ATT; + + if((bta_gattc_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_GATT_SDP_DB_SIZE)) != NULL) + { + attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST; + attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST; + + SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, &uuid, num_attrs, attr_list); + + if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda, bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback)) + { + GKI_freebuf(bta_gattc_cb.p_sdp_db); + bta_gattc_cb.p_sdp_db = NULL; + } + else + { + bta_gattc_cb.sdp_conn_id = conn_id; + status = BTA_GATT_OK; + } + } + return status; +} +/******************************************************************************* +** +** Function bta_gattc_disc_res_cback +** bta_gattc_disc_cmpl_cback +** +** Description callback functions to GATT client stack. +** +** Returns void +** +*******************************************************************************/ +void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data) +{ + tBTA_GATTC_SERV * p_srvc_cb = NULL; + BOOLEAN pri_srvc; + + p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id); + + if (p_srvc_cb != NULL) + { + switch (disc_type) + { + case GATT_DISC_SRVC_ALL: + /* discover services result, add services into a service list */ + bta_gattc_add_srvc_to_list(p_srvc_cb, + p_data->handle, + p_data->value.group_value.e_handle, + p_data->value.group_value.service_type, + TRUE); + + break; + case GATT_DISC_SRVC_BY_UUID: + bta_gattc_add_srvc_to_list(p_srvc_cb, + p_data->handle, + p_data->value.handle, + p_data->type, + TRUE); + break; + + case GATT_DISC_INC_SRVC: + /* add included service into service list if it's secondary or it never showed up + in the primary service search */ + pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb, + p_data->value.incl_service.s_handle, + p_data->value.incl_service.e_handle, + p_data->value.incl_service.service_type); + + if (!pri_srvc) + bta_gattc_add_srvc_to_list(p_srvc_cb, + p_data->value.incl_service.s_handle, + p_data->value.incl_service.e_handle, + p_data->value.incl_service.service_type, + FALSE); + /* add into database */ + bta_gattc_add_attr_to_cache(p_srvc_cb, + p_data->handle, + &p_data->value.incl_service.service_type, + pri_srvc, + BTA_GATTC_ATTR_TYPE_INCL_SRVC); + break; + + case GATT_DISC_CHAR: + /* add char value into database */ + bta_gattc_add_char_to_list(p_srvc_cb, + p_data->handle, + p_data->value.dclr_value.val_handle, + p_data->value.dclr_value.char_uuid, + p_data->value.dclr_value.char_prop); + break; + + case GATT_DISC_CHAR_DSCPT: + bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0, BTA_GATTC_ATTR_TYPE_CHAR_DESCR); + break; + } + } +} +void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status) +{ + tBTA_GATTC_SERV * p_srvc_cb; + + p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id); + + if (p_srvc_cb != NULL) + { + switch (disc_type) + { + case GATT_DISC_SRVC_ALL: +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx); +#endif + bta_gattc_explore_srvc(conn_id, p_srvc_cb); + break; + + case GATT_DISC_INC_SRVC: + bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb); + + break; + + case GATT_DISC_CHAR: +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx); +#endif + bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb); + break; + + case GATT_DISC_CHAR_DSCPT: + bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb); + break; + } + } +} +/******************************************************************************* +** +** Function bta_gattc_id2handle +** +** Description map GATT ID to handle in a given cache. +** +** Returns the handle mapped. 0 if not found. +** +*******************************************************************************/ +UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id, + tBTA_GATT_ID *p_char_id, tBT_UUID descr_uuid) +{ + tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache; + tBTA_GATTC_CACHE_ATTR *p_attr; + UINT8 j; + UINT16 handle = 0; + tBT_UUID attr_uuid; + BOOLEAN char_map = FALSE, done = FALSE; + + while (p_cache && !done) + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]", + p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16, + p_cache->service_uuid.id.inst_id); +#endif + p_attr = p_cache->p_attr; + + if (bta_gattc_uuid_compare(p_service_id->id.uuid, p_cache->service_uuid.id.uuid, TRUE) && + p_service_id->id.inst_id == p_cache->service_uuid.id.inst_id && + p_cache->service_uuid.is_primary == p_service_id->is_primary) + { + for (j = 0; p_attr; j ++) + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]", + j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type); +#endif + bta_gattc_pack_attr_uuid(p_attr, &attr_uuid); + + if (bta_gattc_uuid_compare(p_char_id->uuid, attr_uuid, TRUE) && + p_char_id->inst_id == p_attr->inst_id) + { + if (descr_uuid.len == 0) + { + handle = p_attr->attr_handle; + done = TRUE; + break; + } + else + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG0("found matching characteristic for the descriptor"); +#endif + char_map = TRUE; + } + } + else if (char_map == TRUE) + { + if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) + { + + if (bta_gattc_uuid_compare(descr_uuid, attr_uuid, TRUE)) + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG0("found descripotor!!"); +#endif + handle = p_attr->attr_handle; + done = TRUE; + break; + } + else + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG0("descriptor UUID not matching"); +#endif + } + } + else /* another char */ + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG0("no matching descriptor found!! start of next characteristic"); +#endif + char_map = FALSE; + done = TRUE; + break; + } + } + p_attr = p_attr->p_next; + } + } + p_cache = p_cache->p_next; + } + + return handle; +} +/******************************************************************************* +** +** Function bta_gattc_handle2id +** +** Description map a handle to GATT ID in a given cache. +** +** Returns FALSE if map can not be found. +** +*******************************************************************************/ + +BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id, + tBTA_GATT_ID *p_char_id, tBT_UUID *p_descr_type) +{ + tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache; + tBTA_GATTC_CACHE_ATTR *p_attr, *p_char = NULL; + UINT8 j; + + memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID)); + memset(p_char_id, 0, sizeof(tBTA_GATT_ID)); + memset(p_descr_type, 0, sizeof(tBT_UUID)); + + while (p_cache) + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]", + p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16, + p_cache->service_uuid.id.inst_id); +#endif + /* a service found */ + if (p_cache->s_handle == handle) + { + memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID)); + + return TRUE; + } + else /* start looking for attributes within the service */ + { + p_attr = p_cache->p_attr; + + for (j = 0; p_attr; j ++) + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]", + j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type); +#endif + if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR) + p_char = p_attr; + + if (handle == p_attr->attr_handle) + { + memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID)); + + if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) + { + bta_gattc_pack_attr_uuid(p_attr, p_descr_type); + + if (p_char != NULL) + { + bta_gattc_pack_attr_uuid(p_char, &p_char_id->uuid); + p_char_id->inst_id = p_char->inst_id; + } + else + { + APPL_TRACE_ERROR0("descriptor does not belong to any chracteristic, error"); + } + } + else + /* is a characterisitc value or included service */ + { + bta_gattc_pack_attr_uuid(p_attr, &p_char_id->uuid); + p_char_id->inst_id =p_attr->inst_id; + } + return TRUE; + } + p_attr = p_attr->p_next; + } + } + p_cache = p_cache->p_next; + } + + return FALSE; +} + +/******************************************************************************* +** +** Function bta_gattc_search_service +** +** Description search local cache for matching service record. +** +** Returns FALSE if map can not be found. +** +*******************************************************************************/ +void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid) +{ + tBTA_GATTC_SERV *p_srcb = p_clcb->p_srcb; + tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache; + tBTA_GATTC cb_data; + + while (p_cache) + { + if (bta_gattc_uuid_compare(uuid, p_cache->service_uuid.id.uuid, FALSE)) + { +//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG3("found service [0x%04x], inst[%d] handle [%d]", + p_cache->service_uuid.id.uuid.uu.uuid16, + p_cache->service_uuid.id.inst_id, + p_cache->s_handle); +//#endif + if (p_clcb->p_rcb->p_cback) + { + memset(&cb_data, 0, sizeof(tBTA_GATTC)); + + cb_data.srvc_res.conn_id = p_clcb->bta_conn_id; + memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid ,sizeof(tBTA_GATT_SRVC_ID)); + + (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data); + //todo (tBTA_GATTC *)&p_cache->service_uuid); + } + } + p_cache = p_cache->p_next; + } +} +/******************************************************************************* +** +** Function bta_gattc_find_record +** +** Description search local cache for matching attribute record. +** +** Parameter p_result: output parameter to store the characteristic/ +** included service GATT ID. +** +** Returns GATT_ERROR is no recording found. BTA_GATT_OK if record found. +** +*******************************************************************************/ +static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb, + tBTA_GATTC_ATTR_TYPE attr_type, + tBTA_GATT_SRVC_ID *p_service_id, + tBTA_GATT_ID *p_start_rec, + tBT_UUID * p_uuid_cond, + tBTA_GATT_ID *p_result, + void *p_param) +{ + tBTA_GATTC_CACHE *p_cache = p_srcb->p_srvc_cache; + tBTA_GATT_STATUS status = BTA_GATT_ERROR; + tBT_UUID uuid_cond = {0}, start_descr = {0}; + UINT8 i, j; + tBTA_GATTC_CACHE_ATTR *p_attr; + BOOLEAN char_found = FALSE, descr_found = FALSE; + + if (p_uuid_cond) + memcpy(&uuid_cond, p_uuid_cond, sizeof(tBT_UUID)); + + for (i = 0; p_cache <= p_srcb->p_cur_srvc && p_cache && status != BTA_GATT_OK; i ++) + { + if (bta_gattc_uuid_compare(p_service_id->id.uuid, p_cache->service_uuid.id.uuid, FALSE) && + p_service_id->id.inst_id == p_cache->service_uuid.id.inst_id && + p_service_id->is_primary == p_cache->service_uuid.is_primary) + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG2("found matching service [0x%04x], inst[%d]", + p_cache->service_uuid.id.uuid.uu.uuid16, + p_cache->service_uuid.id.inst_id); +#endif + p_attr = p_cache->p_attr; + + for (j = 0; p_attr; j ++) + { +#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE) + APPL_TRACE_DEBUG5("\t Attr[%d] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]", + j + 1, p_attr->attr_handle, + p_attr->p_uuid->uuid16, + p_attr->inst_id, + p_attr->attr_type); +#endif + bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid); + + if (p_start_rec != NULL && char_found == FALSE) + { + /* find the starting record first */ + if (bta_gattc_uuid_compare(p_start_rec->uuid, p_result->uuid, FALSE) && + p_start_rec->inst_id == p_attr->inst_id && + (attr_type == p_attr->attr_type || + /* find descriptor would look for characteristic first */ + (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR && p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR))) + { + char_found = TRUE; + } + } + else + { + /* if looking for descriptor, here is the where the descrptor to be found */ + if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR) + { + /* starting descriptor UUID */ + if (p_param != NULL) + memcpy(&start_descr, p_param, sizeof(tBT_UUID)); + /* next characeteristic already, return error */ + if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR) + { + break; + } + else + { + if (start_descr.len != 0 && !descr_found) + { + if (bta_gattc_uuid_compare(start_descr, p_result->uuid, FALSE)) + { + descr_found = TRUE; + } + } + else + { + /* with matching descriptor */ + if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE)) + { + status = BTA_GATT_OK; + break; + } + } + } + } + else + { + if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE) && + attr_type == p_attr->attr_type) + { + + APPL_TRACE_DEBUG0("found char handle mapping characteristic"); + p_result->inst_id = p_attr->inst_id; + + if (p_param != NULL) + { + if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR || + attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC) + { + *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property; + } + } + + status = BTA_GATT_OK; + break; + } + } + } + p_attr = p_attr->p_next; + } + if (status) + { + APPL_TRACE_ERROR0("In the given service, can not find matching record"); + } + break; + } + + p_cache = p_cache->p_next; + } + return status; + +} + +/******************************************************************************* +** +** Function bta_gattc_query_cache +** +** Description search local cache for matching attribute record. +** +** Parameters conn_id: connection ID which identify the server. +** p_srvc_id: the service ID of which the characteristic is belonged to. +** *p_start_rec: start the search from the next record +** after the one identified by *p_start_rec. +** p_uuid_cond: UUID, if NULL find the first available +** characteristic/included service. +** p_output: output parameter which will store the GATT ID +** of the characteristic /included service found. +** +** Returns BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found. +** +*******************************************************************************/ +tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, + tBTA_GATTC_ATTR_TYPE query_type, + tBTA_GATT_SRVC_ID *p_srvc_id, + tBTA_GATT_ID *p_start_rec, + tBT_UUID *p_uuid_cond, + tBTA_GATT_ID *p_output, + void *p_param) +{ + tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id); + tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER; + + /* lock other GKI task */ + GKI_sched_lock(); + + APPL_TRACE_DEBUG0("bta_gattc_query_cache"); + + if (p_clcb != NULL ) + { + if (p_clcb->state == BTA_GATTC_CONN_ST) + { + if (p_clcb->p_srcb && + !p_clcb->p_srcb->p_srvc_list && /* no active discovery */ + p_clcb->p_srcb->p_srvc_cache) + { + status = bta_gattc_find_record(p_clcb->p_srcb, + query_type, + p_srvc_id, + p_start_rec, + p_uuid_cond, + p_output, + p_param); + } + else + { + status = BTA_GATT_ERROR; + APPL_TRACE_ERROR0("No server cache available"); + } + } + else + { + APPL_TRACE_ERROR1("server cache not available, CLCB state = %d", p_clcb->state); + + status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR; + } + } + else + { + APPL_TRACE_ERROR1("Unknown conn ID: %d", conn_id); + } + GKI_sched_unlock(); + + return status; +} + +/******************************************************************************* +** +** Function bta_gattc_rebuild_cache +** +** Description rebuild server cache from NV cache. +** +** Parameters +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr, + tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index) +{ + /* first attribute loading, initialize buffer */ + APPL_TRACE_ERROR0("bta_gattc_rebuild_cache"); + if (attr_index == 0) + { + while (p_srvc_cb->cache_buffer.p_first) + GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer)); + + if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL) + { + APPL_TRACE_ERROR0("allocate cache buffer failed, no resources"); + } + else + { + p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL; + } + } + + while (num_attr > 0 && p_attr != NULL) + { + switch (p_attr->attr_type) + { + case BTA_GATTC_ATTR_TYPE_SRVC: + bta_gattc_add_srvc_to_cache(p_srvc_cb, + p_attr->s_handle, + p_attr->e_handle, + &p_attr->uuid, + p_attr->is_primary, + p_attr->id); + break; + + case BTA_GATTC_ATTR_TYPE_CHAR: + case BTA_GATTC_ATTR_TYPE_CHAR_DESCR: + case BTA_GATTC_ATTR_TYPE_INCL_SRVC: + bta_gattc_add_attr_to_cache(p_srvc_cb, + p_attr->s_handle, + &p_attr->uuid, + p_attr->prop, + p_attr->attr_type); + break; + } + p_attr ++; + num_attr --; + } +} + +/******************************************************************************* +** +** Function bta_gattc_fill_nv_attr +** +** Description fill a NV attribute entry value +** +** Returns None. +** +*******************************************************************************/ +void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle, + UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop, BOOLEAN is_primary) +{ + p_attr->s_handle = s_handle; + p_attr->e_handle = e_handle; + p_attr->attr_type = type; + p_attr->is_primary = is_primary; + p_attr->id = id; + p_attr->prop = prop; + + memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID)); +} +/******************************************************************************* +** +** Function bta_gattc_cache_save +** +** Description save the server cache into NV +** +** Returns None. +** +*******************************************************************************/ +BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id) +{ + tBTA_GATTC_CACHE *p_cur_srvc = p_srvc_cb->p_srvc_cache; + UINT8 i = 0; + UINT16 offset = 0; + tBTA_GATTC_NV_ATTR nv_attr[BTA_GATTC_NV_LOAD_MAX]; + tBTA_GATTC_CACHE_ATTR *p_attr; + tBT_UUID uuid; + + while (p_cur_srvc && i < BTA_GATTC_NV_LOAD_MAX) + { + if (offset ++ >= p_srvc_cb->attr_index) + { + bta_gattc_fill_nv_attr(&nv_attr[i++], + BTA_GATTC_ATTR_TYPE_SRVC, + p_cur_srvc->s_handle, + p_cur_srvc->e_handle, + p_cur_srvc->service_uuid.id.inst_id, + p_cur_srvc->service_uuid.id.uuid, + 0, + p_cur_srvc->service_uuid.is_primary); + } + + p_attr = p_cur_srvc->p_attr; + + for (; p_attr && i < BTA_GATTC_NV_LOAD_MAX ; offset ++, p_attr = p_attr->p_next) + { + if (offset >= p_srvc_cb->attr_index) + { + if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16) + { + uuid.uu.uuid16 = p_attr->p_uuid->uuid16; + } + else + { + memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128); + } + + bta_gattc_fill_nv_attr(&nv_attr[i++], + p_attr->attr_type, + p_attr->attr_handle, + 0, + p_attr->inst_id, + uuid, + p_attr->property, + FALSE); + } + } + p_cur_srvc = p_cur_srvc->p_next; + } + + if (i > 0) + { + bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i, + nv_attr, p_srvc_cb->attr_index, conn_id); + + p_srvc_cb->attr_index += i; + + return TRUE; + } + else + { + return FALSE; + } +} +#endif /* BTA_GATT_INCLUDED */ + diff --git a/bta/gatt/bta_gattc_ci.c b/bta/gatt/bta_gattc_ci.c new file mode 100644 index 0000000..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 + +#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 + +#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 +#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 + +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 +#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 + +#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 +#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 +#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 + +/***************************************************************************** +** 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 +#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(®_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 + +#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 +#include +#include + +#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 + +#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 + +#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 + +#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; imdep_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; imdep_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 + +#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 + +#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 + +#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; jsup_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 +#include + +#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; inum_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; iin_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; kin_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;itime = time_min + i; + bta_hl_co_save_mdl(p_acb->app_id, s_arr[i], p_mdl); + } + } + + +} + + + +/******************************************************************************* +** +** Function bta_hl_is_mdl_exsit_in_mcl +** +** Description This function checks whether the MDL ID +** has already existed in teh MCL or not +** +** Returns BOOLEAN - TRUE exist +** FALSE does not exist +** +*******************************************************************************/ +BOOLEAN bta_hl_is_mdl_exsit_in_mcl(UINT8 app_idx, BD_ADDR bd_addr, + tBTA_HL_MDL_ID mdl_id) +{ + tBTA_HL_MDL_CFG *p_mdl; + BOOLEAN found = FALSE; + UINT8 i; + + for (i = 0; i< BTA_HL_NUM_MDL_CFGS; i++) + { + p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i); + if (p_mdl->active && + !memcmp(p_mdl->peer_bd_addr, bd_addr,BD_ADDR_LEN)) + { + if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS) + { + if (p_mdl->mdl_id == mdl_id) + { + found = TRUE; + break; + } + } + else + { + found = TRUE; + break; + } + } + } + + return found; +} + +/******************************************************************************* +** +** Function bta_hl_delete_mdl_cfg +** +** Description This function delete the specified MDL ID +** +** Returns BOOLEAN - TRUE Success +** FALSE Failed +** +*******************************************************************************/ +BOOLEAN bta_hl_delete_mdl_cfg(UINT8 app_idx, BD_ADDR bd_addr, + tBTA_HL_MDL_ID mdl_id) +{ + tBTA_HL_MDL_CFG *p_mdl; + BOOLEAN success = FALSE; + UINT8 i; + tBTA_HL_APP_CB *p_acb= BTA_HL_GET_APP_CB_PTR(app_idx); + UINT8 app_id = p_acb->app_id; + + for (i = 0; i< BTA_HL_NUM_MDL_CFGS; i++) + { + p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i); + if (p_mdl->active && + !memcmp(p_mdl->peer_bd_addr, bd_addr,BD_ADDR_LEN)) + { + if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS) + { + if (p_mdl->mdl_id == mdl_id) + { + bta_hl_co_delete_mdl(app_id, i); + memset(p_mdl, 0, sizeof(tBTA_HL_MDL_CFG)); + success = TRUE; + break; + } + } + else + { + bta_hl_co_delete_mdl(app_id, i); + memset(p_mdl, 0, sizeof(tBTA_HL_MDL_CFG)); + success = TRUE; + } + } + } + + return success; +} + + +/******************************************************************************* +** +** Function bta_hl_is_mdl_value_valid +** +** +** Description This function checks the specified MDL ID is in valid range or not +** +** Returns BOOLEAN - TRUE Success +** FALSE Failed +** +** note: mdl_id range 0x0000 reserved, +** 0x0001-oxFEFF dynamic range, +** 0xFF00-0xFFFE reserved, +** 0xFFFF indicates all MDLs (for delete operation only) +** +*******************************************************************************/ +BOOLEAN bta_hl_is_mdl_value_valid(tBTA_HL_MDL_ID mdl_id) +{ + BOOLEAN status = TRUE; + + if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS) + { + if (mdl_id != 0) + { + if (mdl_id > BTA_HL_MAX_MDL_VAL ) + { + status = FALSE; + } + } + else + { + status = FALSE; + } + } + + return status; +} + +/******************************************************************************* +** +** Function bta_hl_find_mdep_cfg_idx +** +** Description This function finds the MDEP configuration index based +** on the local MDEP ID +** +** Returns BOOLEAN - TRUE found +** FALSE not found +** +*******************************************************************************/ +BOOLEAN bta_hl_find_mdep_cfg_idx(UINT8 app_idx, tBTA_HL_MDEP_ID local_mdep_id, + UINT8 *p_mdep_cfg_idx) +{ + tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx); + tBTA_HL_SUP_FEATURE *p_sup_feature= &p_acb->sup_feature; + BOOLEAN found =FALSE; + UINT8 i; + + for (i=0; i< p_sup_feature->num_of_mdeps; i++) + { + if ( p_sup_feature->mdep[i].mdep_id == local_mdep_id) + { + found = TRUE; + *p_mdep_cfg_idx = i; + break; + } + } + +#if BTA_HL_DEBUG == TRUE + if (!found) + { + APPL_TRACE_DEBUG3("bta_hl_find_mdep_cfg_idx found=%d mdep_idx=%d local_mdep_id=%d ", + found,i, local_mdep_id ); + } +#endif + return found; +} + + +/******************************************************************************* +** +** Function bta_hl_find_rxtx_apdu_size +** +** Description This function finds the maximum APDU rx and tx sizes based on +** the MDEP configuration data +** +** Returns void +** +*******************************************************************************/ +void bta_hl_find_rxtx_apdu_size(UINT8 app_idx, UINT8 mdep_cfg_idx, + UINT16 *p_rx_apu_size, + UINT16 *p_tx_apu_size) +{ + tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx); + tBTA_HL_MDEP_CFG *p_mdep_cfg; + UINT8 i; + UINT16 max_rx_apdu_size=0, max_tx_apdu_size=0; + + p_mdep_cfg = &p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg; + + + for (i=0; i< p_mdep_cfg->num_of_mdep_data_types ; i++) + { + + if (max_rx_apdu_size < p_mdep_cfg->data_cfg[i].max_rx_apdu_size) + { + max_rx_apdu_size = p_mdep_cfg->data_cfg[i].max_rx_apdu_size; + } + + if (max_tx_apdu_size < p_mdep_cfg->data_cfg[i].max_tx_apdu_size) + { + max_tx_apdu_size = p_mdep_cfg->data_cfg[i].max_tx_apdu_size; + } + } + + + *p_rx_apu_size = max_rx_apdu_size; + *p_tx_apu_size = max_tx_apdu_size; + +#if BTA_HL_DEBUG == TRUE + APPL_TRACE_DEBUG2("bta_hl_find_rxtx_apdu_size max_rx_apdu_size=%d max_tx_apdu_size=%d ", + max_rx_apdu_size, max_tx_apdu_size ); +#endif + + +} + +/******************************************************************************* +** +** Function bta_hl_validate_peer_cfg +** +** Description This function validates the peer DCH configuration +** +** Returns BOOLEAN - TRUE validation is successful +** FALSE validation failed +** +*******************************************************************************/ +BOOLEAN bta_hl_validate_peer_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx, + tBTA_HL_MDEP_ID peer_mdep_id, + tBTA_HL_MDEP_ROLE peer_mdep_role, + UINT8 sdp_idx) +{ + tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx); + tBTA_HL_MDL_CB *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx); + tBTA_HL_SDP_REC *p_rec; + BOOLEAN peer_found =FALSE; + UINT8 i; + + APPL_TRACE_DEBUG1("bta_hl_validate_peer_cfg sdp_idx=%d", sdp_idx); + + + if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID) + { + return TRUE; + } + + p_rec = &p_mcb->sdp.sdp_rec[sdp_idx]; + for (i=0; i< p_rec->num_mdeps; i++) + { + if ( (p_rec->mdep_cfg[i].mdep_id == peer_mdep_id) && + (p_rec->mdep_cfg[i].mdep_role == peer_mdep_role)) + { + peer_found = TRUE; + + break; + } + } + + +#if BTA_HL_DEBUG == TRUE + if (!peer_found) + { + APPL_TRACE_DEBUG1("bta_hl_validate_peer_cfg failed num_mdeps=%d",p_rec->num_mdeps); + } +#endif + return peer_found; +} + + +/******************************************************************************* +** +** Function bta_hl_chk_local_cfg +** +** Description This function check whether the local DCH configuration is OK or not +** +** Returns tBTA_HL_STATUS - OK - local DCH configuration is OK +** NO_FIRST_RELIABLE - the streaming DCH configuration +** is not OK and it needs to use +** reliable DCH configuration +** +*******************************************************************************/ +tBTA_HL_STATUS bta_hl_chk_local_cfg(UINT8 app_idx, UINT8 mcl_idx, + UINT8 mdep_cfg_idx, + tBTA_HL_DCH_CFG local_cfg) +{ + tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx); + tBTA_HL_STATUS status = BTA_HL_STATUS_OK; + + if ( mdep_cfg_idx && + (p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SOURCE) && + (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx)) && + (local_cfg != BTA_HL_DCH_CFG_RELIABLE)) + { + status = BTA_HL_STATUS_NO_FIRST_RELIABLE; + APPL_TRACE_ERROR0("BTA_HL_STATUS_INVALID_DCH_CFG"); + } + + return status; +} + + +/******************************************************************************* +** +** Function bta_hl_validate_reconnect_params +** +** Description This function validates the reconnect parameters +** +** Returns BOOLEAN - TRUE validation is successful +** FALSE validation failed +*******************************************************************************/ +BOOLEAN bta_hl_validate_reconnect_params(UINT8 app_idx, UINT8 mcl_idx, + tBTA_HL_API_DCH_RECONNECT *p_reconnect, + UINT8 *p_mdep_cfg_idx, UINT8 *p_mdl_cfg_idx) +{ + tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx); + tBTA_HL_SUP_FEATURE *p_sup_feature = &p_acb->sup_feature; + UINT8 num_mdeps; + UINT8 mdl_cfg_idx; + BOOLEAN local_mdep_id_found =FALSE; + BOOLEAN mdl_cfg_found =FALSE; + BOOLEAN status=FALSE; + UINT8 i, in_use_mdl_idx; + +#if BTA_HL_DEBUG == TRUE + APPL_TRACE_DEBUG1("bta_hl_validate_reconnect_params mdl_id=%d", p_reconnect->mdl_id); +#endif + if (bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_reconnect->mdl_id, &mdl_cfg_idx)) + { + mdl_cfg_found = TRUE; + } + +#if BTA_HL_DEBUG == TRUE + if (!mdl_cfg_found) + { + APPL_TRACE_DEBUG0("mdl_cfg_found not found"); + } +#endif + + + if (mdl_cfg_found) + { + num_mdeps = p_sup_feature->num_of_mdeps; + for (i=0; i< num_mdeps ; i++) + { + if ( p_sup_feature->mdep[i].mdep_id == p_acb->mdl_cfg[mdl_cfg_idx].local_mdep_id) + { + local_mdep_id_found = TRUE; + *p_mdep_cfg_idx =i; + *p_mdl_cfg_idx = mdl_cfg_idx; + break; + } + } + } + +#if BTA_HL_DEBUG == TRUE + if (!local_mdep_id_found) + { + APPL_TRACE_DEBUG0("local_mdep_id not found"); + } +#endif + + + if (local_mdep_id_found) + { + if (!bta_hl_find_mdl_idx(app_idx,mcl_idx, p_reconnect->mdl_id, &in_use_mdl_idx)) + { + status= TRUE; + } + else + { + APPL_TRACE_ERROR1("mdl_id=%d is curreltly in use",p_reconnect->mdl_id); + } + } + +#if BTA_HL_DEBUG == TRUE + if (!status) + { + APPL_TRACE_DEBUG3("Reconnect validation failed local_mdep_id found=%d mdl_cfg_idx found=%d in_use_mdl_idx=%d ", + local_mdep_id_found, mdl_cfg_found, in_use_mdl_idx); + } +#endif + return status; +} + +/******************************************************************************* +** +** Function bta_hl_find_avail_mcl_idx +** +** Returns BOOLEAN - TRUE found +** FALSE not found +** +*******************************************************************************/ +BOOLEAN bta_hl_find_avail_mcl_idx(UINT8 app_idx, UINT8 *p_mcl_idx) +{ + BOOLEAN found=FALSE; + UINT8 i; + + for (i=0; i < BTA_HL_NUM_MCLS ; i ++) + { + if (!bta_hl_cb.acb[app_idx].mcb[i].in_use) + { + found = TRUE; + *p_mcl_idx = i; + break; + } + } + +#if BTA_HL_DEBUG == TRUE + if (!found) + { + APPL_TRACE_DEBUG2("bta_hl_find_avail_mcl_idx found=%d idx=%d", + found, i); + } +#endif + return found; +} + + + +/******************************************************************************* +** +** Function bta_hl_find_avail_mdl_idx +** +** Description This function finds an available MDL control block index +** +** Returns BOOLEAN - TRUE found +** FALSE not found +** +*******************************************************************************/ +BOOLEAN bta_hl_find_avail_mdl_idx(UINT8 app_idx, UINT8 mcl_idx, + UINT8 *p_mdl_idx) +{ + tBTA_HL_MCL_CB *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx); + BOOLEAN found=FALSE; + UINT8 i; + + for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++) + { + if (!p_mcb->mdl[i].in_use) + { + memset((void *)&p_mcb->mdl[i],0, sizeof(tBTA_HL_MDL_CB)); + found = TRUE; + *p_mdl_idx = i; + break; + } + } + +#if BTA_HL_DEBUG == TRUE + if (!found) + { + APPL_TRACE_DEBUG2("bta_hl_find_avail_mdl_idx found=%d idx=%d", + found, i); + } +#endif + return found; +} + +/******************************************************************************* +** +** Function bta_hl_is_a_duplicate_id +** +** Description This function finds the application has been used or not +** +** Returns BOOLEAN - TRUE the app_id is a duplicate ID +** FALSE not a duplicate ID +*******************************************************************************/ +BOOLEAN bta_hl_is_a_duplicate_id(UINT8 app_id) +{ + BOOLEAN is_duplicate=FALSE; + UINT8 i; + + for (i=0; i < BTA_HL_NUM_APPS ; i ++) + { + if (bta_hl_cb.acb[i].in_use && + (bta_hl_cb.acb[i].app_id == app_id)) + { + is_duplicate = TRUE; + + break; + } + } + +#if BTA_HL_DEBUG == TRUE + if (is_duplicate) + { + + APPL_TRACE_DEBUG2("bta_hl_is_a_duplicate_id app_id=%d is_duplicate=%d", + app_id, is_duplicate); + } +#endif + + return is_duplicate; +} + + +/******************************************************************************* +** +** Function bta_hl_find_avail_app_idx +** +** Description This function finds an available application control block index +** +** Returns BOOLEAN - TRUE found +** FALSE not found +** +*******************************************************************************/ +BOOLEAN bta_hl_find_avail_app_idx(UINT8 *p_idx) +{ + BOOLEAN found=FALSE; + UINT8 i; + + for (i=0; i < BTA_HL_NUM_APPS ; i ++) + { + if (!bta_hl_cb.acb[i].in_use) + { + found = TRUE; + *p_idx = i; + break; + } + } + +#if BTA_HL_DEBUG == TRUE + if (!found) + { + APPL_TRACE_DEBUG2("bta_hl_find_avail_app_idx found=%d app_idx=%d", + found, i); + } +#endif + return found; +} + +/******************************************************************************* +** +** Function bta_hl_app_registration +** +** Description This function registers an HDP application MCAP and DP +** +** Returns tBTA_HL_STATUS -registration status +** +*******************************************************************************/ +tBTA_HL_STATUS bta_hl_app_registration(UINT8 app_idx) +{ + tBTA_HL_STATUS status = BTA_HL_STATUS_OK; + tBTA_HL_APP_CB *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx); + tMCA_REG reg; + tMCA_CS mca_cs; + UINT8 i, num_of_mdeps; + + +#if BTA_HL_DEBUG == TRUE + APPL_TRACE_DEBUG1("bta_hl_app_registration app_idx=%d", app_idx); +#endif + + reg.ctrl_psm = p_acb->ctrl_psm; + reg.data_psm = p_acb->data_psm; + reg.sec_mask = p_acb->sec_mask; + reg.rsp_tout = BTA_HL_MCAP_RSP_TOUT; + + if ( (p_acb->app_handle = (tBTA_HL_APP_HANDLE) MCA_Register(®, bta_hl_mcap_ctrl_cback))!=0) + { + mca_cs.type = MCA_TDEP_ECHO; + mca_cs.max_mdl = BTA_HL_NUM_MDLS_PER_MDEP; + mca_cs.p_data_cback = bta_hl_mcap_data_cback; + + if (MCA_CreateDep((tMCA_HANDLE)p_acb->app_handle, + &(p_acb->sup_feature.mdep[0].mdep_id), + &mca_cs) == MCA_SUCCESS) + { + if (p_acb->sup_feature.mdep[0].mdep_id != BTA_HL_ECHO_TEST_MDEP_ID) + { + status = BTA_HL_STATUS_MCAP_REG_FAIL; + APPL_TRACE_ERROR1("BAD MDEP ID for echo test mdep_id=%d", + p_acb->sup_feature.mdep[0].mdep_id ); + } + } + else + { + status = BTA_HL_STATUS_MCAP_REG_FAIL; + APPL_TRACE_ERROR0("MCA_CreateDep for echo test(mdep_id=0) failed"); + } + + + if ((status == BTA_HL_STATUS_OK) && + bta_hl_co_get_num_of_mdep(p_acb->app_id, &num_of_mdeps)) + { + p_acb->sup_feature.num_of_mdeps = num_of_mdeps+1; + + for (i=1; isup_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 + +#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 + +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 + +/***************************************************************************** +** +** 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 +#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 +#include +#include +#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 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" 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 , "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 "++E+N", we don't want to commit + ** them until we know it is not "END:MSG". + ** + ** 'idx_end' is used to index through the "END:MSG 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 sequence? */ + if ( c == END_MSG[idx_end] ) + { + /* Yes. Did we get to the end of "END:MSG"? */ + 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 , is this ? */ + 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 */ + 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 (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 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 (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 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 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++END:MSG */ +#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 +#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, ¶m); + + /* 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, ¶m); + 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 +#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 +#include +#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 + +#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; jstate != 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 = ⌖ + /* 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; isess_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 + +#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 +#include +#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 ( "\n" \ + "\n" \ + "\n" ) + +#define BTA_MSE_FOLDER_LISTING_END ( "" ) +#define BTA_MSE_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 ( "\n" ) +#define BTA_MSE_MSG_LISTING_END ( "" ) + + +// 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; jhdr.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, "\n" + "\n"); + + /* 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_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, ¶m); +} + +/******************************************************************************* +** +** 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; ioper, 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; ibd_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; ibd_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 +#include +#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 +#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 *)¶m); + + /* 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 *)¶m); + + /* 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 *)¶m); + } + } +} + +/******************************************************************************* +** +** 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 *)¶m); + + /* 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 +#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 + +#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 +#include +#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 +#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 +#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 + +#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 +#include +#include +#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 *)¶m); + } + } + 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 *)¶m); + } + + /* 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 + + +/* RX and TX data flow mask */ +#define BTA_PAN_RX_MASK 0x0F +#define BTA_PAN_TX_MASK 0xF0 + +/******************************************************************************* +** +** Function bta_pan_conn_state_cback +** +** Description Connection state callback from Pan profile +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_conn_state_cback(UINT16 handle, BD_ADDR bd_addr, tPAN_RESULT state, + BOOLEAN is_role_change, UINT8 src_role, UINT8 dst_role) +{ + + tBTA_PAN_CONN * p_buf; + tBTA_PAN_SCB *p_scb; + + + if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL) + { + if((state == PAN_SUCCESS) && !is_role_change) + { + p_buf->hdr.event = BTA_PAN_CONN_OPEN_EVT; + if((p_scb = bta_pan_scb_by_handle(handle)) == NULL) + { + /* allocate an scb */ + p_scb = bta_pan_scb_alloc(); + + } + /* we have exceeded maximum number of connections */ + if(!p_scb) + { + PAN_Disconnect (handle); + return; + } + + p_scb->handle = handle; + p_scb->local_role = src_role; + p_scb->peer_role = dst_role; + p_scb->pan_flow_enable = TRUE; + bdcpy(p_scb->bd_addr, bd_addr); + GKI_init_q(&p_scb->data_queue); + + if(src_role == PAN_ROLE_CLIENT) + p_scb->app_id = bta_pan_cb.app_id[0]; + else if (src_role == PAN_ROLE_GN_SERVER) + p_scb->app_id = bta_pan_cb.app_id[1]; + else if (src_role == PAN_ROLE_NAP_SERVER) + p_scb->app_id = bta_pan_cb.app_id[2]; + + } + else if((state != PAN_SUCCESS) && !is_role_change) + { + p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT; + + } + else + { + return; + } + + p_buf->result = state; + p_buf->hdr.layer_specific = handle; + bta_sys_sendmsg(p_buf); + + } + + + +} + +/******************************************************************************* +** +** Function bta_pan_data_flow_cb +** +** Description Data flow status callback from PAN +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_data_flow_cb(UINT16 handle, tPAN_RESULT result) +{ + BT_HDR *p_buf; + tBTA_PAN_SCB *p_scb; + + if((p_scb = bta_pan_scb_by_handle(handle)) == NULL) + return; + + if(result == PAN_TX_FLOW_ON) + { + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->layer_specific = handle; + p_buf->event = BTA_PAN_BNEP_FLOW_ENABLE_EVT; + bta_sys_sendmsg(p_buf); + } + bta_pan_co_rx_flow(handle, p_scb->app_id, TRUE); + + } + else if(result == PAN_TX_FLOW_OFF) + { + + p_scb->pan_flow_enable = FALSE; + bta_pan_co_rx_flow(handle, p_scb->app_id, FALSE); + + } + + +} + + +/******************************************************************************* +** +** Function bta_pan_data_buf_ind_cback +** +** Description data indication callback from pan profile +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_data_buf_ind_cback(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf, + BOOLEAN ext, BOOLEAN forward) +{ + tBTA_PAN_SCB *p_scb; + BT_HDR * p_event; + BT_HDR *p_new_buf; + + if ( sizeof(tBTA_PAN_DATA_PARAMS) > p_buf->offset ) + { + /* offset smaller than data structure in front of actual data */ + p_new_buf = (BT_HDR *)GKI_getpoolbuf( PAN_POOL_ID ); + if(!p_new_buf) + { + APPL_TRACE_WARNING0("Cannot get a PAN GKI buffer"); + GKI_freebuf( p_buf ); + return; + } + else + { + memcpy( (UINT8 *)(p_new_buf+1)+sizeof(tBTA_PAN_DATA_PARAMS), (UINT8 *)(p_buf+1)+p_buf->offset, p_buf->len ); + p_new_buf->len = p_buf->len; + p_new_buf->offset = sizeof(tBTA_PAN_DATA_PARAMS); + GKI_freebuf( p_buf ); + } + } + else + { + p_new_buf = p_buf; + } + /* copy params into the space before the data */ + bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->src, src); + bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->dst, dst); + ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->protocol = protocol; + ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->ext = ext; + ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->forward = forward; + + + if((p_scb = bta_pan_scb_by_handle(handle)) == NULL) + { + + GKI_freebuf( p_new_buf ); + return; + } + + GKI_enqueue(&p_scb->data_queue, p_new_buf); + if ((p_event = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_event->layer_specific = handle; + p_event->event = BTA_PAN_RX_FROM_BNEP_READY_EVT; + bta_sys_sendmsg(p_event); + } + +} + + +/******************************************************************************* +** +** Function bta_pan_pfilt_ind_cback +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_pfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result, + UINT16 num_filters, UINT8 *p_filters) +{ + + bta_pan_co_pfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL), + num_filters, p_filters); + + +} + + +/******************************************************************************* +** +** Function bta_pan_mfilt_ind_cback +** +** Description +** +** +** Returns void +** +*******************************************************************************/ +static void bta_pan_mfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result, + UINT16 num_mfilters, UINT8 *p_mfilters) +{ + + bta_pan_co_mfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL), + num_mfilters, p_mfilters); +} + + + +/******************************************************************************* +** +** Function bta_pan_enable +** +** Description +** +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_enable(tBTA_PAN_DATA *p_data) +{ + tPAN_REGISTER reg_data; + UINT16 initial_discoverability; + UINT16 initial_connectability; + UINT16 d_window; + UINT16 d_interval; + UINT16 c_window; + UINT16 c_interval; + + bta_pan_cb.p_cback = p_data->api_enable.p_cback; + + reg_data.pan_conn_state_cb = bta_pan_conn_state_cback; + reg_data.pan_bridge_req_cb = NULL; + reg_data.pan_data_buf_ind_cb = bta_pan_data_buf_ind_cback; + reg_data.pan_data_ind_cb = NULL; + reg_data.pan_pfilt_ind_cb = bta_pan_pfilt_ind_cback; + reg_data.pan_mfilt_ind_cb = bta_pan_mfilt_ind_cback; + reg_data.pan_tx_data_flow_cb = bta_pan_data_flow_cb; + + /* read connectability and discoverability settings. + Pan profile changes the settings. We have to change it back to + be consistent with other bta subsystems */ + initial_connectability = BTM_ReadConnectability(&c_window, &c_interval); + initial_discoverability = BTM_ReadDiscoverability(&d_window, &d_interval); + + + PAN_Register (®_data); + + + /* set it back to original value */ + BTM_SetDiscoverability(initial_discoverability, d_window, d_interval); + BTM_SetConnectability(initial_connectability, c_window, c_interval); + + bta_pan_cb.flow_mask = bta_pan_co_init(&bta_pan_cb.q_level); + bta_pan_cb.p_cback(BTA_PAN_ENABLE_EVT, NULL); + +} + +/******************************************************************************* +** +** Function bta_pan_set_role +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_pan_set_role(tBTA_PAN_DATA *p_data) +{ + tPAN_RESULT status; + tBTA_PAN_SET_ROLE set_role; + UINT8 sec[3]; + + + bta_pan_cb.app_id[0] = p_data->api_set_role.user_app_id; + bta_pan_cb.app_id[1] = p_data->api_set_role.gn_app_id; + bta_pan_cb.app_id[2] = p_data->api_set_role.nap_app_id; + + sec[0] = p_data->api_set_role.user_sec_mask; + sec[1] = p_data->api_set_role.gn_sec_mask; + sec[2] = p_data->api_set_role.nap_sec_mask; + + /* set security correctly in api and here */ + status = PAN_SetRole(p_data->api_set_role.role, sec, + p_data->api_set_role.user_name, + p_data->api_set_role.gn_name, + p_data->api_set_role.nap_name); + + if(status == PAN_SUCCESS) + { + if(p_data->api_set_role.role & PAN_ROLE_NAP_SERVER ) + bta_sys_add_uuid(UUID_SERVCLASS_NAP); + else + bta_sys_remove_uuid(UUID_SERVCLASS_NAP); + + if(p_data->api_set_role.role & PAN_ROLE_GN_SERVER ) + bta_sys_add_uuid(UUID_SERVCLASS_GN); + else + bta_sys_remove_uuid(UUID_SERVCLASS_GN); + + if(p_data->api_set_role.role & PAN_ROLE_CLIENT ) + bta_sys_add_uuid(UUID_SERVCLASS_PANU); + else + bta_sys_remove_uuid(UUID_SERVCLASS_PANU); + + set_role.role = p_data->api_set_role.role; + bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role); + } + /* if status is not success clear everything */ + else + { + PAN_SetRole(0, 0, NULL, NULL, NULL); + + bta_sys_remove_uuid(UUID_SERVCLASS_NAP); + bta_sys_remove_uuid(UUID_SERVCLASS_GN); + bta_sys_remove_uuid(UUID_SERVCLASS_PANU); + set_role.role = 0; + bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role); + } + +} + + + +/******************************************************************************* +** +** Function bta_pan_disable +** +** Description +** +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_disable(void) +{ + + BT_HDR *p_buf; + tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0]; + UINT8 i; + + + /* close all connections */ + PAN_SetRole (0, NULL, NULL, NULL, NULL); + +#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE) + bta_sys_remove_uuid(UUID_SERVCLASS_NAP); + bta_sys_remove_uuid(UUID_SERVCLASS_GN); + bta_sys_remove_uuid(UUID_SERVCLASS_PANU); +#endif + /* free all queued up data buffers */ + for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++) + { + if (p_scb->in_use) + { + while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL) + GKI_freebuf(p_buf); + + bta_pan_co_close(p_scb->handle, p_scb->app_id); + + } + } + + + + PAN_Deregister(); + +} + +/******************************************************************************* +** +** Function bta_pan_open +** +** Description +** +** Returns void +** +*******************************************************************************/ +void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + tPAN_RESULT status; + tBTA_PAN_OPEN data; + tBTA_PAN_OPENING opening; + + + status = PAN_Connect (p_data->api_open.bd_addr, p_data->api_open.local_role, p_data->api_open.peer_role, + &p_scb->handle); + + + if(status == PAN_SUCCESS) + { + + bdcpy(p_scb->bd_addr, p_data->api_open.bd_addr); + p_scb->local_role = p_data->api_open.local_role; + p_scb->peer_role = p_data->api_open.peer_role; + bdcpy(opening.bd_addr, p_data->api_open.bd_addr); + opening.handle = p_scb->handle; + bta_pan_cb.p_cback(BTA_PAN_OPENING_EVT, (tBTA_PAN *)&opening); + + + } + else + { + bta_pan_scb_dealloc(p_scb); + bdcpy(data.bd_addr, p_data->api_open.bd_addr); + data.status = BTA_PAN_FAIL; + bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data); + } + +} + + +/******************************************************************************* +** +** Function bta_pan_close +** +** Description +** +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_api_close (tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + tBTA_PAN_CONN * p_buf; + + PAN_Disconnect (p_scb->handle); + + + /* send an event to BTA so that application will get the connection + close event */ + if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL) + { + p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT; + + p_buf->hdr.layer_specific = p_scb->handle; + bta_sys_sendmsg(p_buf); + + } +} + + +/******************************************************************************* +** +** Function bta_pan_conn_open +** +** Description process connection open event +** +** Returns void +** +*******************************************************************************/ +void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + + tBTA_PAN_OPEN data; + + bdcpy(data.bd_addr, p_scb->bd_addr); + data.handle = p_scb->handle; + data.local_role = p_scb->local_role; + data.peer_role = p_scb->peer_role; + + if(p_data->conn.result == PAN_SUCCESS) + { + data.status = BTA_PAN_SUCCESS; + bta_pan_co_open(p_scb->handle, p_scb->app_id, p_scb->local_role, p_scb->peer_role, p_scb->bd_addr); + + } + else + { + bta_pan_scb_dealloc(p_scb); + data.status = BTA_PAN_FAIL; + } + + p_scb->pan_flow_enable = TRUE; + p_scb->app_flow_enable = TRUE; + + bta_sys_conn_open( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr); + + bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data); + + +} + +/******************************************************************************* +** +** Function bta_pan_conn_close +** +** Description process connection close event +** +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + + tBTA_PAN_CLOSE data; + BT_HDR *p_buf; + + data.handle = p_data->hdr.layer_specific; + + + bta_sys_conn_close( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr); + + /* free all queued up data buffers */ + while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL) + GKI_freebuf(p_buf); + + GKI_init_q(&p_scb->data_queue); + + bta_pan_co_close(p_scb->handle, p_scb->app_id); + + bta_pan_scb_dealloc(p_scb); + + bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, (tBTA_PAN *)&data); + +} + + + + +/******************************************************************************* +** +** Function bta_pan_rx_path +** +** Description Handle data on the RX path (data sent from the phone to +** BTA). +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + /* if data path configured for rx pull */ + if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PULL) + { + /* if we can accept data */ + if (p_scb->pan_flow_enable == TRUE) + { + /* call application callout function for rx path */ + bta_pan_co_rx_path(p_scb->handle, p_scb->app_id); + } + } + /* else data path configured for rx push */ + else + { + + } +} + +/******************************************************************************* +** +** Function bta_pan_tx_path +** +** Description Handle the TX data path (data sent from BTA to the phone). +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + + BT_HDR * p_buf; + /* if data path configured for tx pull */ + if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PULL) + { + /* call application callout function for tx path */ + bta_pan_co_tx_path(p_scb->handle, p_scb->app_id); + + /* free data that exceeds queue level */ + while(p_scb->data_queue.count > bta_pan_cb.q_level) + GKI_freebuf(GKI_dequeue(&p_scb->data_queue)); + } + /* if configured for zero copy push */ + else if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PUSH_BUF) + { + /* if app can accept data */ + if (p_scb->app_flow_enable == TRUE) + { + /* read data from the queue */ + if ((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL) + { + /* send data to application */ + bta_pan_co_tx_writebuf(p_scb->handle, + p_scb->app_id, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->src, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol, + p_buf, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext, + ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward); + + } + /* free data that exceeds queue level */ + while(p_scb->data_queue.count > bta_pan_cb.q_level) + GKI_freebuf(GKI_dequeue(&p_scb->data_queue)); + + /* if there is more data to be passed to + upper layer */ + if(p_scb->data_queue.count) + { + if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL) + { + p_buf->layer_specific = p_scb->handle; + p_buf->event = BTA_PAN_RX_FROM_BNEP_READY_EVT; + bta_sys_sendmsg(p_buf); + } + + } + + } + } +} + +/******************************************************************************* +** +** Function bta_pan_tx_flow +** +** Description Set the application flow control state. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + p_scb->app_flow_enable = p_data->ci_tx_flow.enable; +} + +/******************************************************************************* +** +** Function bta_pan_write_buf +** +** Description Handle a bta_pan_ci_rx_writebuf() and send data to PAN. +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PUSH_BUF) + { + + PAN_WriteBuf (p_scb->handle, + ((tBTA_PAN_DATA_PARAMS *)p_data)->dst, + ((tBTA_PAN_DATA_PARAMS *)p_data)->src, + ((tBTA_PAN_DATA_PARAMS *)p_data)->protocol, + (BT_HDR *)p_data, + ((tBTA_PAN_DATA_PARAMS *)p_data)->ext); + + } +} + +/******************************************************************************* +** +** Function bta_pan_free_buf +** +** Description Frees the data buffer during closing state +** +** +** Returns void +** +*******************************************************************************/ +void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data) +{ + + GKI_freebuf(p_data); + +} + +#endif /* PAN_INCLUDED */ diff --git a/bta/pan/bta_pan_api.c b/bta/pan/bta_pan_api.c new file mode 100644 index 0000000..5a84668 --- /dev/null +++ b/bta/pan/bta_pan_api.c @@ -0,0 +1,202 @@ +/***************************************************************************** +** +** Name: bta_pan_api.c +** +** Description: This is the implementation of the API for PAN +** subsystem of BTA, Widcomm's Bluetooth application +** layer for mobile phones. +** +** Copyright (c) 2004-2011, Broadcom Corp., All Rights Reserved. +** Broadcom Bluetooth Core. Proprietary and confidential. +** +*****************************************************************************/ + +#include "bt_target.h" + +#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE) + +#include "bta_api.h" +#include "bta_sys.h" +#include "pan_api.h" +#include "gki.h" +#include "bta_pan_api.h" +#include "bta_pan_int.h" +#include "bd.h" +#include + +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 + +#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 +#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 +#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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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, ¶m_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 +#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 +#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 = ⌖ + + /* 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 + +#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 +#include +#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 ( "\n" \ + "\n" \ + "\n" ) + +#define BTA_PBS_FOLDER_LISTING_END ( "" ) +#define BTA_PBS_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,"<"); + buf+=4; + break; + case '>': + BCM_STRCPY_S(buf,4,">"); + buf+=4; + break; + case '\"': + BCM_STRCPY_S(buf,6,"""); + buf+=6; + break; + case '\'': + BCM_STRCPY_S(buf,6,"'"); + buf+=6; + break; + case '&': + BCM_STRCPY_S(buf,5,"&"); + 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 +#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; +} + + -- cgit v1.1