summaryrefslogtreecommitdiffstats
path: root/btif/co
diff options
context:
space:
mode:
Diffstat (limited to 'btif/co')
-rw-r--r--btif/co/bta_ag_co.c132
-rw-r--r--btif/co/bta_av_co.c1504
-rw-r--r--btif/co/bta_dm_co.c417
-rw-r--r--btif/co/bta_fs_co.c1181
-rw-r--r--btif/co/bta_hh_co.c276
-rw-r--r--btif/co/bta_hl_co.c459
-rw-r--r--btif/co/bta_pan_co.c334
-rw-r--r--btif/co/bta_sys_co.c57
8 files changed, 4360 insertions, 0 deletions
diff --git a/btif/co/bta_ag_co.c b/btif/co/bta_ag_co.c
new file mode 100644
index 0000000..cd969f8
--- /dev/null
+++ b/btif/co/bta_ag_co.c
@@ -0,0 +1,132 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#include "gki.h"
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_co.h"
+#include "bte_appl.h"
+
+#define LOG_TAG "BTA_AG_CO: "
+
+#ifndef LINUX_NATIVE
+#include <cutils/properties.h>
+#include <cutils/log.h>
+#else
+#include <stdio.h>
+#define LOGI(format, ...) fprintf (stdout, LOG_TAG format"\n", ## __VA_ARGS__)
+#define LOGD(format, ...) fprintf (stdout, LOG_TAG format"\n", ## __VA_ARGS__)
+#define LOGV(format, ...) fprintf (stdout, LOG_TAG format"\n", ## __VA_ARGS__)
+#define LOGE(format, ...) fprintf (stderr, LOG_TAG format"\n", ## __VA_ARGS__)
+#endif
+
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+void bta_ag_co_init(void)
+{
+ BTM_WriteVoiceSettings(AG_VOICE_SETTINGS);
+}
+
+
+/*******************************************************************************
+**
+** 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 has been turned off (xfer)
+** 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
+**
+*******************************************************************************/
+void bta_ag_co_audio_state(UINT16 handle, UINT8 app_id, UINT8 state)
+{
+ BTIF_TRACE_DEBUG2("bta_ag_co_audio_state: handle %d, state %d", handle, 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
+**
+*******************************************************************************/
+void bta_ag_co_data_open(UINT16 handle, tBTA_SERVICE_ID service)
+{
+ BTIF_TRACE_DEBUG2("bta_ag_co_data_open handle:%d service:%d", handle, service);
+}
+
+/*******************************************************************************
+**
+** Function bta_ag_co_data_close
+**
+** Description This function is called by AG when a service level
+** connection is closed
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_ag_co_data_close(UINT16 handle)
+{
+ BTIF_TRACE_DEBUG1("bta_ag_co_data_close handle:%d", 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 phones memory.
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void bta_ag_co_tx_write(UINT16 handle, UINT8 * p_data, UINT16 len)
+{
+ BTIF_TRACE_DEBUG2( "bta_ag_co_tx_write: handle: %d, len: %d", handle, len );
+}
+
diff --git a/btif/co/bta_av_co.c b/btif/co/bta_av_co.c
new file mode 100644
index 0000000..6089532
--- /dev/null
+++ b/btif/co/bta_av_co.c
@@ -0,0 +1,1504 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2004-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the advanced audio/video call-out function implementation for
+ * BTIF.
+ *
+ ******************************************************************************/
+
+#include "string.h"
+#include "a2d_api.h"
+#include "a2d_sbc.h"
+#include "bta_sys.h"
+#include "bta_av_api.h"
+#include "bta_av_co.h"
+#include "bta_av_ci.h"
+#include "bta_av_sbc.h"
+
+#include "btif_media.h"
+#include "sbc_encoder.h"
+#include "btif_av_co.h"
+
+
+/*****************************************************************************
+ ** Constants
+ *****************************************************************************/
+
+#define FUNC_TRACE() APPL_TRACE_DEBUG1("%s", __FUNCTION__);
+
+/* Macro to retrieve the number of elements in a statically allocated array */
+#define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a)/sizeof((__a)[0]))
+
+/* MIN and MAX macros */
+#define BTA_AV_CO_MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+#define BTA_AV_CO_MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+
+/* Macro to convert audio handle to index and vice versa */
+#define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1)
+#define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO)
+
+
+/* Offsets to access codec information in SBC codec */
+#define BTA_AV_CO_SBC_FREQ_CHAN_OFF 3
+#define BTA_AV_CO_SBC_BLOCK_BAND_OFF 4
+#define BTA_AV_CO_SBC_MIN_BITPOOL_OFF 5
+#define BTA_AV_CO_SBC_MAX_BITPOOL_OFF 6
+
+#define BTA_AV_CO_SBC_MAX_BITPOOL 53
+
+/* SCMS-T protect info */
+const UINT8 bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = "\x02\x02\x00";
+
+/* SBC codec capabilities */
+const tA2D_SBC_CIE bta_av_co_sbc_caps =
+{
+ (A2D_SBC_IE_SAMP_FREQ_44), /* samp_freq */
+ (A2D_SBC_IE_CH_MD_MONO | A2D_SBC_IE_CH_MD_STEREO | A2D_SBC_IE_CH_MD_JOINT | A2D_SBC_IE_CH_MD_DUAL), /* ch_mode */
+ (A2D_SBC_IE_BLOCKS_16 | A2D_SBC_IE_BLOCKS_12 | A2D_SBC_IE_BLOCKS_8 | A2D_SBC_IE_BLOCKS_4), /* block_len */
+ (A2D_SBC_IE_SUBBAND_4 | A2D_SBC_IE_SUBBAND_8), /* num_subbands */
+ (A2D_SBC_IE_ALLOC_MD_L | A2D_SBC_IE_ALLOC_MD_S), /* alloc_mthd */
+ BTA_AV_CO_SBC_MAX_BITPOOL, /* max_bitpool */
+ A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
+};
+
+#if !defined(BTIF_AV_SBC_DEFAULT_SAMP_FREQ)
+#define BTIF_AV_SBC_DEFAULT_SAMP_FREQ A2D_SBC_IE_SAMP_FREQ_44
+#endif
+
+/* Default SBC codec configuration */
+const tA2D_SBC_CIE btif_av_sbc_default_config =
+{
+ BTIF_AV_SBC_DEFAULT_SAMP_FREQ, /* samp_freq */
+ A2D_SBC_IE_CH_MD_JOINT, /* ch_mode */
+ A2D_SBC_IE_BLOCKS_16, /* block_len */
+ A2D_SBC_IE_SUBBAND_8, /* num_subbands */
+ A2D_SBC_IE_ALLOC_MD_L, /* alloc_mthd */
+ BTA_AV_CO_SBC_MAX_BITPOOL, /* max_bitpool */
+ A2D_SBC_IE_MIN_BITPOOL /* min_bitpool */
+};
+
+
+/*****************************************************************************
+** Local data
+*****************************************************************************/
+typedef struct
+{
+ UINT8 sep_info_idx; /* local SEP index (in BTA tables) */
+ UINT8 seid; /* peer SEP index (in peer tables) */
+ UINT8 codec_type; /* peer SEP codec type */
+ UINT8 codec_caps[AVDT_CODEC_SIZE]; /* peer SEP codec capabilities */
+ UINT8 num_protect; /* peer SEP number of CP elements */
+ UINT8 protect_info[BTA_AV_CP_INFO_LEN]; /* peer SEP content protection info */
+} tBTA_AV_CO_SINK;
+
+typedef struct
+{
+ BD_ADDR addr; /* address of audio/video peer */
+ tBTA_AV_CO_SINK snks[BTIF_SV_AV_AA_SEP_INDEX]; /* array of supported sinks */
+ UINT8 num_snks; /* total number of sinks at peer */
+ UINT8 num_seps; /* total number of seids at peer */
+ UINT8 num_rx_snks; /* number of received sinks */
+ UINT8 num_sup_snks; /* number of supported sinks in the snks array */
+ tBTA_AV_CO_SINK *p_snk; /* currently selected sink */
+ UINT8 codec_cfg[AVDT_CODEC_SIZE]; /* current codec configuration */
+ BOOLEAN cp_active; /* current CP configuration */
+ BOOLEAN acp; /* acceptor */
+ BOOLEAN recfg_needed; /* reconfiguration is needed */
+ BOOLEAN opened; /* opened */
+ UINT16 mtu; /* maximum transmit unit size */
+} tBTA_AV_CO_PEER;
+
+typedef struct
+{
+ BOOLEAN active;
+ UINT8 flag;
+} tBTA_AV_CO_CP;
+
+typedef struct
+{
+ /* Connected peer information */
+ tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
+ /* Current codec configuration - access to this variable must be protected */
+ tBTIF_AV_CODEC_INFO codec_cfg;
+ tBTIF_AV_CODEC_INFO codec_cfg_setconfig; /* remote peer setconfig preference */
+
+ tBTA_AV_CO_CP cp;
+} tBTA_AV_CO_CB;
+
+/* Control block instance */
+static tBTA_AV_CO_CB bta_av_co_cb;
+
+static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UINT8 *p_codec_cfg);
+static void bta_av_co_audio_peer_reset_config(tBTA_AV_CO_PEER *p_peer);
+static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo);
+static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink);
+static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index);
+static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg);
+
+
+
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_cp_is_active
+ **
+ ** Description Get the current configuration of content protection
+ **
+ ** Returns TRUE if the current streaming has CP, FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_cp_is_active(void)
+{
+ FUNC_TRACE();
+ return bta_av_co_cb.cp.active;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_cp_get_flag
+ **
+ ** Description Get content protection flag
+ ** BTA_AV_CP_SCMS_COPY_NEVER
+ ** BTA_AV_CP_SCMS_COPY_ONCE
+ ** BTA_AV_CP_SCMS_COPY_FREE
+ **
+ ** Returns The current flag value
+ **
+ *******************************************************************************/
+UINT8 bta_av_co_cp_get_flag(void)
+{
+ FUNC_TRACE();
+ return bta_av_co_cb.cp.flag;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_cp_set_flag
+ **
+ ** Description Set content protection flag
+ ** BTA_AV_CP_SCMS_COPY_NEVER
+ ** BTA_AV_CP_SCMS_COPY_ONCE
+ ** BTA_AV_CP_SCMS_COPY_FREE
+ **
+ ** Returns TRUE if setting the SCMS flag is supported else FALSE
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_cp_set_flag(UINT8 cp_flag)
+{
+ FUNC_TRACE();
+
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+#else
+ if (cp_flag != BTA_AV_CP_SCMS_COPY_FREE)
+ {
+ return FALSE;
+ }
+#endif
+ bta_av_co_cb.cp.flag = cp_flag;
+ return TRUE;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_get_peer
+ **
+ ** Description find the peer entry for a given handle
+ **
+ ** Returns the control block
+ **
+ *******************************************************************************/
+static tBTA_AV_CO_PEER *bta_av_co_get_peer(tBTA_AV_HNDL hndl)
+{
+ UINT8 index;
+ FUNC_TRACE();
+
+ index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl);
+
+ /* Sanity check */
+ if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers))
+ {
+ APPL_TRACE_ERROR1("bta_av_co_get_peer peer index out of bounds:%d", index);
+ return NULL;
+ }
+
+ return &bta_av_co_cb.peers[index];
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_init
+ **
+ ** Description This callout function is executed by AV when it is
+ ** started by calling BTA_AvRegister(). 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.
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info, UINT8 *p_num_protect,
+ UINT8 *p_protect_info, UINT8 index)
+{
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG1("bta_av_co_audio_init: %d", index);
+
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ {
+ UINT8 *p = p_protect_info;
+
+ /* Content protection info - support SCMS-T */
+ *p_num_protect = 1;
+ *p++ = BTA_AV_CP_LOSC;
+ UINT16_TO_STREAM(p, BTA_AV_CP_SCMS_T_ID);
+
+ }
+#else
+ /* By default - no content protection info */
+ *p_num_protect = 0;
+ *p_protect_info = 0;
+#endif
+
+ /* reset remote preference through setconfig */
+ bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
+
+ switch (index)
+ {
+ case BTIF_SV_AV_AA_SBC_INDEX:
+ /* Set up for SBC codec */
+ *p_codec_type = BTA_AV_CODEC_SBC;
+
+ /* This should not fail because we are using constants for parameters */
+ A2D_BldSbcInfo(AVDT_MEDIA_AUDIO, (tA2D_SBC_CIE *) &bta_av_co_sbc_caps, p_codec_info);
+
+ /* Codec is valid */
+ return TRUE;
+
+
+ default:
+ /* Not valid */
+ return FALSE;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** 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 void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk,
+ BD_ADDR addr)
+{
+ tBTA_AV_CO_PEER *p_peer;
+
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG3("bta_av_co_audio_disc_res h:x%x num_seps:%d num_snk:%d",
+ hndl, num_seps, num_snk);
+
+ /* Find the peer info */
+ p_peer = bta_av_co_get_peer(hndl);
+ if (p_peer == NULL)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_disc_res could not find peer entry");
+ return;
+ }
+
+ /* Sanity check : this should never happen */
+ if (p_peer->opened)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_disc_res peer already opened");
+ }
+
+ /* Copy the discovery results */
+ bdcpy(p_peer->addr, addr);
+ p_peer->num_snks = num_snk;
+ p_peer->num_seps = num_seps;
+ p_peer->num_rx_snks = 0;
+ p_peer->num_sup_snks = 0;
+}
+
+/*******************************************************************************
+ **
+ ** 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 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)
+
+{
+ UINT8 result = A2D_FAIL;
+ BOOLEAN supported;
+ tBTA_AV_CO_PEER *p_peer;
+ tBTA_AV_CO_SINK *p_sink;
+ UINT8 codec_cfg[AVDT_CODEC_SIZE];
+ UINT8 index;
+
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG3("bta_av_co_audio_getconfig handle:0x%x codec_type:%d seid:%d", hndl, codec_type, seid);
+ APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x",
+ *p_num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
+
+ /* Retrieve the peer info */
+ p_peer = bta_av_co_get_peer(hndl);
+ if (p_peer == NULL)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_getconfig could not find peer entry");
+ return A2D_FAIL;
+ }
+
+ APPL_TRACE_DEBUG4("bta_av_co_audio_getconfig peer(o=%d,n_snks=%d,n_rx_snks=%d,n_sup_snks=%d)",
+ p_peer->opened, p_peer->num_snks, p_peer->num_rx_snks, p_peer->num_sup_snks);
+
+ /* Increment the number of received sinks capabilities */
+ p_peer->num_rx_snks++;
+
+ /* Check if this is a supported configuration */
+ supported = FALSE;
+ switch (codec_type)
+ {
+ case BTA_AV_CODEC_SBC:
+ supported = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ if (supported)
+ {
+ /* If there is room for a new one */
+ if (p_peer->num_sup_snks < BTA_AV_CO_NUM_ELEMENTS(p_peer->snks))
+ {
+ p_sink = &p_peer->snks[p_peer->num_sup_snks++];
+
+ APPL_TRACE_DEBUG6("bta_av_co_audio_getconfig saved caps[%x:%x:%x:%x:%x:%x]",
+ p_codec_info[1], p_codec_info[2], p_codec_info[3],
+ p_codec_info[4], p_codec_info[5], p_codec_info[6]);
+
+ memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
+ p_sink->codec_type = codec_type;
+ p_sink->sep_info_idx = *p_sep_info_idx;
+ p_sink->seid = seid;
+ p_sink->num_protect = *p_num_protect;
+ memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_getconfig no more room for SNK info");
+ }
+ }
+
+ /* If last SNK get capabilities or all supported codec capa retrieved */
+ if ((p_peer->num_rx_snks == p_peer->num_snks) ||
+ (p_peer->num_sup_snks == BTA_AV_CO_NUM_ELEMENTS(p_peer->snks)))
+ {
+ APPL_TRACE_DEBUG0("bta_av_co_audio_getconfig last sink reached");
+
+ /* Protect access to bta_av_co_cb.codec_cfg */
+ GKI_disable();
+
+ /* Find a sink that matches the codec config */
+ if (bta_av_co_audio_peer_supports_codec(p_peer, &index))
+ {
+ /* stop fetching caps once we retrieved a supported codec */
+ if (p_peer->acp)
+ {
+ *p_sep_info_idx = p_peer->num_seps;
+ APPL_TRACE_EVENT0("no need to fetch more SEPs");
+ }
+
+ p_sink = &p_peer->snks[index];
+
+ /* Build the codec configuration for this sink */
+ if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg))
+ {
+ APPL_TRACE_DEBUG6("bta_av_co_audio_getconfig reconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
+ codec_cfg[1], codec_cfg[2], codec_cfg[3],
+ codec_cfg[4], codec_cfg[5], codec_cfg[6]);
+
+ /* Save the new configuration */
+ p_peer->p_snk = p_sink;
+ memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
+
+ /* By default, no content protection */
+ *p_num_protect = 0;
+
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ /* Check if this sink supports SCMS */
+ if (bta_av_co_audio_sink_has_scmst(p_sink))
+ {
+ p_peer->cp_active = TRUE;
+ bta_av_co_cb.cp.active = TRUE;
+ *p_num_protect = BTA_AV_CP_INFO_LEN;
+ memcpy(p_protect_info, bta_av_co_cp_scmst, BTA_AV_CP_INFO_LEN);
+ }
+ else
+ {
+ p_peer->cp_active = FALSE;
+ bta_av_co_cb.cp.active = FALSE;
+ }
+#endif
+
+ /* If acceptor -> reconfig otherwise reply for configuration */
+ if (p_peer->acp)
+ {
+ if (p_peer->recfg_needed)
+ {
+ APPL_TRACE_DEBUG1("bta_av_co_audio_getconfig call BTA_AvReconfig(x%x)", hndl);
+ BTA_AvReconfig(hndl, TRUE, p_sink->sep_info_idx, p_peer->codec_cfg, *p_num_protect, (UINT8 *)bta_av_co_cp_scmst);
+ }
+ }
+ else
+ {
+ *p_sep_info_idx = p_sink->sep_info_idx;
+ memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE);
+ }
+ result = A2D_SUCCESS;
+ }
+ }
+ /* Protect access to bta_av_co_cb.codec_cfg */
+ GKI_enable();
+ }
+ return result;
+}
+
+/*******************************************************************************
+ **
+ ** 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 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)
+
+{
+ tBTA_AV_CO_PEER *p_peer;
+ UINT8 status = A2D_SUCCESS;
+ UINT8 category = A2D_SUCCESS;
+ BOOLEAN recfg_needed = FALSE;
+
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG6("bta_av_co_audio_setconfig p_codec_info[%x:%x:%x:%x:%x:%x]",
+ p_codec_info[1], p_codec_info[2], p_codec_info[3],
+ p_codec_info[4], p_codec_info[5], p_codec_info[6]);
+ APPL_TRACE_DEBUG4("num_protect:0x%02x protect_info:0x%02x%02x%02x",
+ num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
+
+ /* Retrieve the peer info */
+ p_peer = bta_av_co_get_peer(hndl);
+ if (p_peer == NULL)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_setconfig could not find peer entry");
+
+ /* Call call-in rejecting the configuration */
+ bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, FALSE);
+ return;
+ }
+
+ /* Sanity check: should not be opened at this point */
+ if (p_peer->opened)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_setconfig peer already in use");
+ }
+
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ if (num_protect != 0)
+ {
+ /* If CP is supported */
+ if ((num_protect != 1) ||
+ (bta_av_co_cp_is_scmst(p_protect_info) == FALSE))
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_setconfig wrong CP configuration");
+ status = A2D_BAD_CP_TYPE;
+ category = AVDT_ASC_PROTECT;
+ }
+ }
+#else
+ /* Do not support content protection for the time being */
+ if (num_protect != 0)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_setconfig wrong CP configuration");
+ status = A2D_BAD_CP_TYPE;
+ category = AVDT_ASC_PROTECT;
+ }
+#endif
+ if (status == A2D_SUCCESS)
+ {
+ /* Check if codec configuration is supported */
+ if (bta_av_co_audio_media_supports_config(codec_type, p_codec_info))
+ {
+ /* Protect access to bta_av_co_cb.codec_cfg */
+ GKI_disable();
+
+ /* Check if the configuration matches the current codec config */
+ switch (bta_av_co_cb.codec_cfg.id)
+ {
+ case BTIF_AV_CODEC_SBC:
+ if ((codec_type != BTA_AV_CODEC_SBC) || memcmp(p_codec_info, bta_av_co_cb.codec_cfg.info, 5))
+ {
+ recfg_needed = TRUE;
+ }
+ else if ((num_protect == 1) && (!bta_av_co_cb.cp.active))
+ {
+ recfg_needed = TRUE;
+ }
+
+ /* if remote side requests a restricted notify sinks preferred bitpool range as all other params are
+ already checked for validify */
+ APPL_TRACE_EVENT2("remote peer setconfig bitpool range [%d:%d]",
+ p_codec_info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
+ p_codec_info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] );
+
+ bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_SBC;
+ memcpy(bta_av_co_cb.codec_cfg_setconfig.info, p_codec_info, AVDT_CODEC_SIZE);
+ break;
+
+
+ default:
+ APPL_TRACE_ERROR1("bta_av_co_audio_setconfig unsupported cid %d", bta_av_co_cb.codec_cfg.id);
+ recfg_needed = TRUE;
+ break;
+ }
+ /* Protect access to bta_av_co_cb.codec_cfg */
+ GKI_enable();
+ }
+ else
+ {
+ category = AVDT_ASC_CODEC;
+ status = A2D_WRONG_CODEC;
+ }
+ }
+
+ if (status != A2D_SUCCESS)
+ {
+ APPL_TRACE_DEBUG2("bta_av_co_audio_setconfig reject s=%d c=%d", status, category);
+
+ /* Call call-in rejecting the configuration */
+ bta_av_ci_setconfig(hndl, status, category, 0, NULL, FALSE);
+ }
+ else
+ {
+ /* Mark that this is an acceptor peer */
+ p_peer->acp = TRUE;
+ p_peer->recfg_needed = recfg_needed;
+
+ APPL_TRACE_DEBUG1("bta_av_co_audio_setconfig accept reconf=%d", recfg_needed);
+
+ /* Call call-in accepting the configuration */
+ bta_av_ci_setconfig(hndl, A2D_SUCCESS, A2D_SUCCESS, 0, NULL, recfg_needed);
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_open
+ **
+ ** Description This function is called by AV when the audio stream connection
+ ** is opened.
+ **
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+BTA_API void bta_av_co_audio_open(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
+ UINT16 mtu)
+{
+ tBTA_AV_CO_PEER *p_peer;
+
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG2("bta_av_co_audio_open mtu:%d codec_type:%d", mtu, codec_type);
+
+ /* Retrieve the peer info */
+ p_peer = bta_av_co_get_peer(hndl);
+ if (p_peer == NULL)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_setconfig could not find peer entry");
+ }
+ else
+ {
+ p_peer->opened = TRUE;
+ p_peer->mtu = mtu;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_close
+ **
+ ** Description This function is called by AV when the audio stream connection
+ ** is closed.
+ **
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+BTA_API void bta_av_co_audio_close(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT16 mtu)
+
+{
+ tBTA_AV_CO_PEER *p_peer;
+
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG0("bta_av_co_audio_close");
+
+ /* Retrieve the peer info */
+ p_peer = bta_av_co_get_peer(hndl);
+ if (p_peer)
+ {
+ /* Mark the peer closed and clean the peer info */
+ memset(p_peer, 0, sizeof(*p_peer));
+ }
+ else
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_close could not find peer entry");
+ }
+
+ /* reset remote preference through setconfig */
+ bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
+}
+
+/*******************************************************************************
+ **
+ ** 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 void bta_av_co_audio_start(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+ UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr)
+{
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG0("bta_av_co_audio_start");
+
+}
+
+/*******************************************************************************
+ **
+ ** 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)
+{
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG0("bta_av_co_audio_stop");
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_src_data_path
+ **
+ ** Description This function is called to manage data transfer from
+ ** the audio codec to AVDTP.
+ **
+ ** Returns Pointer to the GKI buffer to send, NULL if no buffer to send
+ **
+ *******************************************************************************/
+BTA_API void * bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type, UINT32 *p_len,
+ UINT32 *p_timestamp)
+{
+ BT_HDR *p_buf;
+ FUNC_TRACE();
+
+ p_buf = btif_media_aa_readbuf();
+ if (p_buf != NULL)
+ {
+ switch (codec_type)
+ {
+ case BTA_AV_CODEC_SBC:
+ /* In media packet SBC, the following information is available:
+ * p_buf->layer_specific : number of SBC frames in the packet
+ * p_buf->word[0] : timestamp
+ */
+ /* Retrieve the timestamp information from the media packet */
+ *p_timestamp = *((UINT32 *) (p_buf + 1));
+
+ /* Set up packet header */
+ bta_av_sbc_bld_hdr(p_buf, p_buf->layer_specific);
+ break;
+
+
+ default:
+ APPL_TRACE_ERROR1("bta_av_co_audio_src_data_path Unsupported codec type (%d)", codec_type);
+ break;
+ }
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ {
+ UINT8 *p;
+ if (bta_av_co_cp_is_active())
+ {
+ p_buf->len++;
+ p_buf->offset--;
+ p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+ *p = bta_av_co_cp_get_flag();
+ }
+ }
+#endif
+ }
+ return p_buf;
+}
+
+/*******************************************************************************
+ **
+ ** 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
+ **
+ *******************************************************************************/
+void bta_av_co_audio_drop(tBTA_AV_HNDL hndl)
+{
+ FUNC_TRACE();
+
+ APPL_TRACE_ERROR1("bta_av_co_audio_drop dropped: x%x", hndl);
+}
+
+/*******************************************************************************
+ **
+ ** 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
+ **
+ *******************************************************************************/
+void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, UINT16 delay)
+{
+ FUNC_TRACE();
+
+ APPL_TRACE_ERROR2("bta_av_co_audio_delay handle: x%x, delay:0x%x", hndl, delay);
+}
+
+
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_codec_build_config
+ **
+ ** Description Build the codec configuration
+ **
+ ** Returns TRUE if the codec was built successfully, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_audio_codec_build_config(const UINT8 *p_codec_caps, UINT8 *p_codec_cfg)
+{
+ FUNC_TRACE();
+
+ memset(p_codec_cfg, 0, AVDT_CODEC_SIZE);
+
+ switch (bta_av_co_cb.codec_cfg.id)
+ {
+ case BTIF_AV_CODEC_SBC:
+ /* only copy the relevant portions for this codec to avoid issues when
+ comparing codec configs covering larger codec sets than SBC (7 bytes) */
+ memcpy(p_codec_cfg, bta_av_co_cb.codec_cfg.info, BTA_AV_CO_SBC_MAX_BITPOOL_OFF+1);
+
+ /* Update the bit pool boundaries with the codec capabilities */
+ p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
+ p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF] = p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
+
+ APPL_TRACE_EVENT2("bta_av_co_audio_codec_build_config : bitpool min %d, max %d",
+ p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
+ p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
+ break;
+ default:
+ APPL_TRACE_ERROR1("bta_av_co_audio_codec_build_config: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_codec_cfg_matches_caps
+ **
+ ** Description Check if a codec config matches a codec capabilities
+ **
+ ** Returns TRUE if it codec config is supported, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_audio_codec_cfg_matches_caps(UINT8 codec_id, const UINT8 *p_codec_caps, const UINT8 *p_codec_cfg)
+{
+ FUNC_TRACE();
+
+ switch(codec_id)
+ {
+ case BTIF_AV_CODEC_SBC:
+
+ APPL_TRACE_EVENT4("bta_av_co_audio_codec_cfg_matches_caps : min %d/%d max %d/%d",
+ p_codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
+ p_codec_cfg[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
+ p_codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF],
+ p_codec_cfg[BTA_AV_CO_SBC_MAX_BITPOOL_OFF]);
+
+ /* Must match all items exactly except bitpool boundaries which can be adjusted */
+ if (!((p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF] & p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF]) &&
+ (p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF] & p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF])))
+ {
+ APPL_TRACE_EVENT4("FALSE %x %x %x %x",
+ p_codec_caps[BTA_AV_CO_SBC_FREQ_CHAN_OFF],
+ p_codec_cfg[BTA_AV_CO_SBC_FREQ_CHAN_OFF],
+ p_codec_caps[BTA_AV_CO_SBC_BLOCK_BAND_OFF],
+ p_codec_cfg[BTA_AV_CO_SBC_BLOCK_BAND_OFF]);
+ return FALSE;
+ }
+ break;
+
+
+ default:
+ APPL_TRACE_ERROR1("bta_av_co_audio_codec_cfg_matches_caps: unsupported codec id %d", codec_id);
+ return FALSE;
+ break;
+ }
+ APPL_TRACE_EVENT0("TRUE");
+
+ return TRUE;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_codec_match
+ **
+ ** Description Check if a codec capabilities supports the codec config
+ **
+ ** Returns TRUE if the connection supports this codec, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_audio_codec_match(const UINT8 *p_codec_caps)
+{
+ FUNC_TRACE();
+
+ return bta_av_co_audio_codec_cfg_matches_caps(bta_av_co_cb.codec_cfg.id, p_codec_caps, bta_av_co_cb.codec_cfg.info);
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_peer_reset_config
+ **
+ ** Description Reset the peer codec configuration
+ **
+ ** Returns Nothing
+ **
+ *******************************************************************************/
+static void bta_av_co_audio_peer_reset_config(tBTA_AV_CO_PEER *p_peer)
+{
+ FUNC_TRACE();
+
+ /* Indicate that there is no currently selected sink */
+ p_peer->p_snk = NULL;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_cp_is_scmst
+ **
+ ** Description Check if a content protection service is SCMS-T
+ **
+ ** Returns TRUE if this CP is SCMS-T, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_cp_is_scmst(const UINT8 *p_protectinfo)
+{
+ UINT16 cp_id;
+ FUNC_TRACE();
+
+ if (*p_protectinfo >= BTA_AV_CP_LOSC)
+ {
+ p_protectinfo++;
+ STREAM_TO_UINT16(cp_id, p_protectinfo);
+ if (cp_id == BTA_AV_CP_SCMS_T_ID)
+ {
+ APPL_TRACE_DEBUG0("bta_av_co_cp_is_scmst: SCMS-T found");
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_sink_has_scmst
+ **
+ ** Description Check if a sink supports SCMS-T
+ **
+ ** Returns TRUE if the sink supports this CP, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink)
+{
+ UINT8 index;
+ const UINT8 *p;
+ FUNC_TRACE();
+
+ /* Check if sink supports SCMS-T */
+ index = p_sink->num_protect;
+ p = &p_sink->protect_info[0];
+
+ while (index)
+ {
+ if (bta_av_co_cp_is_scmst(p))
+ {
+ return TRUE;
+ }
+ /* Move to the next SC */
+ p += *p + 1;
+ /* Decrement the SC counter */
+ index--;
+ }
+ APPL_TRACE_DEBUG0("bta_av_co_audio_sink_has_scmst: SCMS-T not found");
+ return FALSE;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_sink_supports_cp
+ **
+ ** Description Check if a sink supports the current content protection
+ **
+ ** Returns TRUE if the sink supports this CP, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK *p_sink)
+{
+ FUNC_TRACE();
+
+ /* Check if content protection is enabled for this stream */
+ if (bta_av_co_cp_get_flag() != BTA_AV_CP_SCMS_COPY_FREE)
+ {
+ return bta_av_co_audio_sink_has_scmst(p_sink);
+ }
+ else
+ {
+ APPL_TRACE_DEBUG0("bta_av_co_audio_sink_supports_cp: not required");
+ return TRUE;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_peer_supports_codec
+ **
+ ** Description Check if a connection supports the codec config
+ **
+ ** Returns TRUE if the connection supports this codec, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_audio_peer_supports_codec(tBTA_AV_CO_PEER *p_peer, UINT8 *p_snk_index)
+{
+ int index;
+ UINT8 codec_type;
+ FUNC_TRACE();
+
+ /* Configure the codec type to look for */
+ codec_type = bta_av_co_cb.codec_cfg.id;
+
+
+ for (index = 0; index < p_peer->num_sup_snks; index++)
+ {
+ if (p_peer->snks[index].codec_type == codec_type)
+ {
+ switch (bta_av_co_cb.codec_cfg.id)
+ {
+ case BTIF_AV_CODEC_SBC:
+ if (p_snk_index) *p_snk_index = index;
+ return bta_av_co_audio_codec_match(p_peer->snks[index].codec_caps);
+ break;
+
+
+ default:
+ APPL_TRACE_ERROR1("bta_av_co_audio_peer_supports_codec: unsupported codec id %d", bta_av_co_cb.codec_cfg.id);
+ return FALSE;
+ break;
+ }
+ }
+ }
+ return FALSE;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_media_supports_config
+ **
+ ** Description Check if the media source supports a given configuration
+ **
+ ** Returns TRUE if the media source supports this config, FALSE otherwise
+ **
+ *******************************************************************************/
+static BOOLEAN bta_av_co_audio_media_supports_config(UINT8 codec_type, const UINT8 *p_codec_cfg)
+{
+ FUNC_TRACE();
+
+ switch (codec_type)
+ {
+ case BTA_AV_CODEC_SBC:
+ if (bta_av_sbc_cfg_in_cap((UINT8 *)p_codec_cfg, (tA2D_SBC_CIE *)&bta_av_co_sbc_caps))
+ {
+ return FALSE;
+ }
+ break;
+
+
+ default:
+ APPL_TRACE_ERROR1("bta_av_co_audio_media_supports_config unsupported codec type %d", codec_type);
+ return FALSE;
+ break;
+ }
+ return TRUE;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_codec_supported
+ **
+ ** Description Check if all opened connections are compatible with a codec
+ ** configuration and content protection
+ **
+ ** Returns TRUE if all opened devices support this codec, FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_codec_supported(tBTIF_STATUS *p_status)
+{
+ UINT8 index;
+ UINT8 snk_index;
+ tBTA_AV_CO_PEER *p_peer;
+ tBTA_AV_CO_SINK *p_sink;
+ UINT8 codec_cfg[AVDT_CODEC_SIZE];
+ UINT8 num_protect = 0;
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ BOOLEAN cp_active;
+#endif
+
+ FUNC_TRACE();
+
+ APPL_TRACE_DEBUG0("bta_av_co_audio_codec_supported");
+
+ /* Check AV feeding is supported */
+ *p_status = BTIF_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED;
+
+ for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++)
+ {
+ p_peer = &bta_av_co_cb.peers[index];
+ if (p_peer->opened)
+ {
+ if (bta_av_co_audio_peer_supports_codec(p_peer, &snk_index))
+ {
+ p_sink = &p_peer->snks[snk_index];
+
+ /* Check that this sink is compatible with the CP */
+ if (!bta_av_co_audio_sink_supports_cp(p_sink))
+ {
+ APPL_TRACE_DEBUG2("bta_av_co_audio_codec_supported sink %d of peer %d doesn't support cp",
+ snk_index, index);
+ *p_status = BTIF_ERROR_SRV_AV_CP_NOT_SUPPORTED;
+ return FALSE;
+ }
+
+ /* Build the codec configuration for this sink */
+ if (bta_av_co_audio_codec_build_config(p_sink->codec_caps, codec_cfg))
+ {
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ /* Check if this sink supports SCMS */
+ cp_active = bta_av_co_audio_sink_has_scmst(p_sink);
+#endif
+ /* Check if this is a new configuration (new sink or new config) */
+ if ((p_sink != p_peer->p_snk) ||
+ (memcmp(codec_cfg, p_peer->codec_cfg, AVDT_CODEC_SIZE))
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ || (p_peer->cp_active != cp_active)
+#endif
+ )
+ {
+ /* Save the new configuration */
+ p_peer->p_snk = p_sink;
+ memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ p_peer->cp_active = cp_active;
+ if (p_peer->cp_active)
+ {
+ bta_av_co_cb.cp.active = TRUE;
+ num_protect = BTA_AV_CP_INFO_LEN;
+ }
+ else
+ {
+ bta_av_co_cb.cp.active = FALSE;
+ }
+#endif
+ APPL_TRACE_DEBUG1("bta_av_co_audio_codec_supported call BTA_AvReconfig(x%x)", BTA_AV_CO_AUDIO_INDX_TO_HNDL(index));
+ BTA_AvReconfig(BTA_AV_CO_AUDIO_INDX_TO_HNDL(index), TRUE, p_sink->sep_info_idx,
+ p_peer->codec_cfg, num_protect, (UINT8 *)bta_av_co_cp_scmst);
+ }
+ }
+ }
+ else
+ {
+ APPL_TRACE_DEBUG1("bta_av_co_audio_codec_supported index %d doesn't support codec", index);
+ return FALSE;
+ }
+ }
+ }
+
+ *p_status = BTIF_SUCCESS;
+ return TRUE;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_codec_reset
+ **
+ ** Description Reset the current codec configuration
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void bta_av_co_audio_codec_reset(void)
+{
+ GKI_disable();
+ FUNC_TRACE();
+
+ /* Reset the current configuration to SBC */
+ bta_av_co_cb.codec_cfg.id = BTIF_AV_CODEC_SBC;
+
+ if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, (tA2D_SBC_CIE *)&btif_av_sbc_default_config, bta_av_co_cb.codec_cfg.info) != A2D_SUCCESS)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_codec_reset A2D_BldSbcInfo failed");
+ }
+
+ GKI_enable();
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_set_codec
+ **
+ ** Description Set the current codec configuration from the feeding type.
+ ** This function is starting to modify the configuration, it
+ ** should be protected.
+ **
+ ** Returns TRUE if successful, FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_set_codec(const tBTIF_AV_MEDIA_FEEDINGS *p_feeding, tBTIF_STATUS *p_status)
+{
+ tA2D_SBC_CIE sbc_config;
+ tBTIF_AV_CODEC_INFO new_cfg;
+
+ FUNC_TRACE();
+
+ /* Check AV feeding is supported */
+ *p_status = BTIF_ERROR_SRV_AV_FEEDING_NOT_SUPPORTED;
+
+ APPL_TRACE_DEBUG1("bta_av_co_audio_set_codec cid=%d", p_feeding->format);
+
+ /* Supported codecs */
+ switch (p_feeding->format)
+ {
+ case BTIF_AV_CODEC_PCM:
+ new_cfg.id = BTIF_AV_CODEC_SBC;
+
+ sbc_config = btif_av_sbc_default_config;
+ if ((p_feeding->cfg.pcm.num_channel != 1) &&
+ (p_feeding->cfg.pcm.num_channel != 2))
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_set_codec PCM channel number unsupported");
+ return FALSE;
+ }
+ if ((p_feeding->cfg.pcm.bit_per_sample != 8) &&
+ (p_feeding->cfg.pcm.bit_per_sample != 16))
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_set_codec PCM sample size unsupported");
+ return FALSE;
+ }
+ switch (p_feeding->cfg.pcm.sampling_freq)
+ {
+ case 8000:
+ case 12000:
+ case 16000:
+ case 24000:
+ case 32000:
+ case 48000:
+ sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_48;
+ break;
+
+ case 11025:
+ case 22050:
+ case 44100:
+ sbc_config.samp_freq = A2D_SBC_IE_SAMP_FREQ_44;
+ break;
+ default:
+ APPL_TRACE_ERROR0("bta_av_co_audio_set_codec PCM sampling frequency unsupported");
+ return FALSE;
+ break;
+ }
+ /* Build the codec config */
+ if (A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &sbc_config, new_cfg.info) != A2D_SUCCESS)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_set_codec A2D_BldSbcInfo failed");
+ return FALSE;
+ }
+ break;
+
+
+ default:
+ APPL_TRACE_ERROR0("bta_av_co_audio_set_codec Feeding format unsupported");
+ return FALSE;
+ break;
+ }
+
+ /* The new config was correctly built */
+ bta_av_co_cb.codec_cfg = new_cfg;
+
+
+ /* Check all devices support it */
+ *p_status = BTIF_SUCCESS;
+ return bta_av_co_audio_codec_supported(p_status);
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_get_sbc_config
+ **
+ ** Description Retrieves the SBC codec configuration. If the codec in use
+ ** is not SBC, return the default SBC codec configuration.
+ **
+ ** Returns TRUE if codec is SBC, FALSE otherwise
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_audio_get_sbc_config(tA2D_SBC_CIE *p_sbc_config, UINT16 *p_minmtu)
+{
+ BOOLEAN result = FALSE;
+ UINT8 index, jndex;
+ tBTA_AV_CO_PEER *p_peer;
+ tBTA_AV_CO_SINK *p_sink;
+
+ APPL_TRACE_EVENT1("bta_av_co_cb.codec_cfg.id : codec 0x%x", bta_av_co_cb.codec_cfg.id);
+
+ /* Minimum MTU is by default very large */
+ *p_minmtu = 0xFFFF;
+
+ GKI_disable();
+ if (bta_av_co_cb.codec_cfg.id == BTIF_AV_CODEC_SBC)
+ {
+ if (A2D_ParsSbcInfo(p_sbc_config, bta_av_co_cb.codec_cfg.info, FALSE) == A2D_SUCCESS)
+ {
+ for (index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); index++)
+ {
+ p_peer = &bta_av_co_cb.peers[index];
+ if (p_peer->opened)
+ {
+ if (p_peer->mtu < *p_minmtu)
+ {
+ *p_minmtu = p_peer->mtu;
+ }
+ for (jndex = 0; jndex < p_peer->num_sup_snks; jndex++)
+ {
+ p_sink = &p_peer->snks[jndex];
+ if (p_sink->codec_type == A2D_MEDIA_CT_SBC)
+ {
+ /* Update the bitpool boundaries of the current config */
+ p_sbc_config->min_bitpool =
+ BTA_AV_CO_MAX(p_sink->codec_caps[BTA_AV_CO_SBC_MIN_BITPOOL_OFF],
+ p_sbc_config->min_bitpool);
+ p_sbc_config->max_bitpool =
+ BTA_AV_CO_MIN(p_sink->codec_caps[BTA_AV_CO_SBC_MAX_BITPOOL_OFF],
+ p_sbc_config->max_bitpool);
+ APPL_TRACE_EVENT2("bta_av_co_audio_get_sbc_config : sink bitpool min %d, max %d",
+ p_sbc_config->min_bitpool, p_sbc_config->max_bitpool);
+ break;
+ }
+ }
+ }
+ }
+ result = TRUE;
+ }
+ }
+
+ if (!result)
+ {
+ /* Not SBC, still return the default values */
+ *p_sbc_config = btif_av_sbc_default_config;
+ }
+ GKI_enable();
+
+ return result;
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_audio_discard_config
+ **
+ ** Description Discard the codec configuration of a connection
+ **
+ ** Returns Nothing
+ **
+ *******************************************************************************/
+void bta_av_co_audio_discard_config(tBTA_AV_HNDL hndl)
+{
+ tBTA_AV_CO_PEER *p_peer;
+
+ FUNC_TRACE();
+
+ /* Find the peer info */
+ p_peer = bta_av_co_get_peer(hndl);
+ if (p_peer == NULL)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_audio_discard_config could not find peer entry");
+ return;
+ }
+
+ /* Reset the peer codec configuration */
+ bta_av_co_audio_peer_reset_config(p_peer);
+}
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_init
+ **
+ ** Description Initialization
+ **
+ ** Returns Nothing
+ **
+ *******************************************************************************/
+void bta_av_co_init(void)
+{
+ FUNC_TRACE();
+
+ /* Reset the control block */
+ memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb));
+
+ bta_av_co_cb.codec_cfg_setconfig.id = BTIF_AV_CODEC_NONE;
+
+#if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE)
+ bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_NEVER);
+#else
+ bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_FREE);
+#endif
+
+ /* Reset the current config */
+ bta_av_co_audio_codec_reset();
+}
+
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_peer_cp_supported
+ **
+ ** Description Checks if the peer supports CP
+ **
+ ** Returns TRUE if the peer supports CP
+ **
+ *******************************************************************************/
+BOOLEAN bta_av_co_peer_cp_supported(tBTA_AV_HNDL hndl)
+{
+ tBTA_AV_CO_PEER *p_peer;
+ tBTA_AV_CO_SINK *p_sink;
+ UINT8 index;
+
+ FUNC_TRACE();
+
+ /* Find the peer info */
+ p_peer = bta_av_co_get_peer(hndl);
+ if (p_peer == NULL)
+ {
+ APPL_TRACE_ERROR0("bta_av_co_peer_cp_supported could not find peer entry");
+ return FALSE;
+ }
+
+ for (index = 0; index < p_peer->num_sup_snks; index++)
+ {
+ p_sink = &p_peer->snks[index];
+ if (p_sink->codec_type == A2D_MEDIA_CT_SBC)
+ {
+ return bta_av_co_audio_sink_has_scmst(p_sink);
+ }
+ }
+ APPL_TRACE_ERROR0("bta_av_co_peer_cp_supported did not find SBC sink");
+ return FALSE;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function bta_av_co_get_remote_bitpool_pref
+ **
+ ** Description Check if remote side did a setconfig within the limits
+ ** of our exported bitpool range. If set we will set the
+ ** remote preference.
+ **
+ ** Returns TRUE if config set, FALSE otherwize
+ **
+ *******************************************************************************/
+
+BOOLEAN bta_av_co_get_remote_bitpool_pref(UINT8 *min, UINT8 *max)
+{
+ /* check if remote peer did a set config */
+ if (bta_av_co_cb.codec_cfg_setconfig.id == BTIF_AV_CODEC_NONE)
+ return FALSE;
+
+ *min = bta_av_co_cb.codec_cfg_setconfig.info[BTA_AV_CO_SBC_MIN_BITPOOL_OFF];
+ *max = bta_av_co_cb.codec_cfg_setconfig.info[BTA_AV_CO_SBC_MAX_BITPOOL_OFF];
+
+ return TRUE;
+}
+
+
diff --git a/btif/co/bta_dm_co.c b/btif/co/bta_dm_co.c
new file mode 100644
index 0000000..611af2d
--- /dev/null
+++ b/btif/co/bta_dm_co.c
@@ -0,0 +1,417 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_dm_co.h"
+#include "bta_dm_ci.h"
+#if (BTM_OOB_INCLUDED == TRUE)
+#include "btif_dm.h"
+#endif
+/*******************************************************************************
+**
+** Function bta_dm_co_get_compress_memory
+**
+** Description This callout function is executed by DM to get memory for compression
+
+** Parameters id - BTA SYS ID
+** memory_p - memory return by callout
+** memory_size - memory size
+**
+** Returns TRUE for success, FALSE for fail.
+**
+*******************************************************************************/
+BOOLEAN bta_dm_co_get_compress_memory(tBTA_SYS_ID id, UINT8 **memory_p, UINT32 *memory_size)
+{
+ return TRUE;
+}
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+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)
+{
+#if (BTM_OOB_INCLUDED == TRUE)
+ btif_dm_set_oob_for_io_req(p_oob_data);
+#endif
+ BTIF_TRACE_DEBUG1("bta_dm_co_io_req *p_oob_data = %d", *p_oob_data);
+ BTIF_TRACE_DEBUG1("bta_dm_co_io_req *p_io_cap = %d", *p_io_cap);
+ BTIF_TRACE_DEBUG1("bta_dm_co_io_req *p_auth_req = %d", *p_auth_req);
+ BTIF_TRACE_DEBUG1("bta_dm_co_io_req is_orig = %d", 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.
+**
+*******************************************************************************/
+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.
+**
+*******************************************************************************/
+void bta_dm_co_lk_upgrade(BD_ADDR bd_addr, BOOLEAN *p_upgrade )
+{
+}
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+void bta_dm_co_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r)
+{
+ BTIF_TRACE_DEBUG1("bta_dm_co_loc_oob, valid = %d", valid);
+#ifdef BTIF_DM_OOB_TEST
+ btif_dm_proc_loc_oob(valid, c, r);
+#endif
+}
+
+/*******************************************************************************
+**
+** 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
+** Need to call bta_dm_ci_rmt_oob() in response
+**
+** Parameters bd_addr - The peer device
+**
+** Returns void.
+**
+*******************************************************************************/
+void bta_dm_co_rmt_oob(BD_ADDR bd_addr)
+{
+ BT_OCTET16 p_c;
+ BT_OCTET16 p_r;
+ BOOLEAN result = FALSE;
+
+#ifdef BTIF_DM_OOB_TEST
+ result = btif_dm_proc_rmt_oob(bd_addr, p_c, p_r);
+#endif
+
+ BTIF_TRACE_DEBUG1("bta_dm_co_rmt_oob: result=%d",result);
+ bta_dm_ci_rmt_oob(result, bd_addr, p_c, p_r);
+}
+
+#endif /* BTM_OOB_INCLUDED */
+
+
+// REMOVE FOR BLUEDROID ?
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTM_SCO_INCLUDED == TRUE)
+
+/*******************************************************************************
+**
+** Function btui_sco_codec_callback
+**
+** Description Callback for btui codec.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+static void btui_sco_codec_callback(UINT16 event, UINT16 sco_handle)
+{
+ bta_dm_sco_ci_data_ready(event, sco_handle);
+}
+/*******************************************************************************
+**
+** 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 tBTA_DM_SCO_ROUTE_TYPE: SCO routing configuration type.
+**
+*******************************************************************************/
+tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
+ tBTA_CODEC_INFO * p_codec_type, UINT8 app_id)
+{
+ tBTM_SCO_ROUTE_TYPE route = BTA_DM_SCO_ROUTE_PCM;
+
+ BTIF_TRACE_DEBUG0("bta_dm_sco_co_init");
+
+ /* set up SCO routing configuration if SCO over HCI app ID is used and run time
+ configuration is set to SCO over HCI */
+ /* HS invoke this call-out */
+ if (
+#if (BTA_HS_INCLUDED == TRUE ) && (BTA_HS_INCLUDED == TRUE)
+ (app_id == BTUI_DM_SCO_4_HS_APP_ID && btui_cfg.hs_sco_over_hci) ||
+#endif
+ /* AG invoke this call-out */
+ (app_id != BTUI_DM_SCO_4_HS_APP_ID && btui_cfg.ag_sco_over_hci ))
+ {
+ route = btui_cb.sco_hci = BTA_DM_SCO_ROUTE_HCI;
+ }
+ /* no codec is is used for the SCO data */
+ if (p_codec_type->codec_type == BTA_SCO_CODEC_PCM && route == BTA_DM_SCO_ROUTE_HCI)
+ {
+ /* initialize SCO codec */
+ if (!btui_sco_codec_init(rx_bw, tx_bw))
+ {
+ BTIF_TRACE_ERROR0("codec initialization exception!");
+ }
+ }
+
+ return route;
+}
+
+
+
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_open
+**
+** Description This function is executed when a SCO connection is open.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event)
+{
+ tBTUI_SCO_CODEC_CFG cfg;
+
+ if (btui_cb.sco_hci)
+ {
+ BTIF_TRACE_DEBUG2("bta_dm_sco_co_open handle:%d pkt_size:%d", handle, pkt_size);
+ /* use dedicated SCO buffer pool for SCO TX data */
+ cfg.pool_id = HCI_SCO_POOL_ID;
+ cfg.p_cback = btui_sco_codec_callback;
+ cfg.pkt_size = pkt_size;
+ cfg.cb_event = event;
+ /* open and start the codec */
+ btui_sco_codec_open(&cfg);
+ btui_sco_codec_start(handle);
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_close
+**
+** Description This function is called when a SCO connection is closed
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_sco_co_close(void)
+{
+ if (btui_cb.sco_hci)
+ {
+ BTIF_TRACE_DEBUG0("bta_dm_sco_co_close close codec");
+ /* close sco codec */
+ btui_sco_codec_close();
+
+ btui_cb.sco_hci = FALSE;
+ }
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_in_data
+**
+** Description This function is called to send incoming SCO data to application.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_sco_co_in_data(BT_HDR *p_buf)
+{
+ if (btui_cfg.sco_use_mic)
+ btui_sco_codec_inqdata (p_buf);
+ else
+ GKI_freebuf(p_buf);
+}
+
+/*******************************************************************************
+**
+** Function bta_dm_sco_co_out_data
+**
+** Description This function is called to send SCO data over HCI.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_dm_sco_co_out_data(BT_HDR **p_buf)
+{
+ btui_sco_codec_readbuf(p_buf);
+}
+
+#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE ) && (BTM_SCO_INCLUDED == TRUE)*/
+
+
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function bta_dm_co_le_io_key_req
+**
+** Description This callout function is executed by DM to get BLE key information
+** before SMP pairing gets going.
+**
+** Parameters bd_addr - The peer device
+** *p_max_key_size - max key size local device supported.
+** *p_init_key - initiator keys.
+** *p_resp_key - responder keys.
+**
+** Returns void.
+**
+*******************************************************************************/
+void bta_dm_co_le_io_key_req(BD_ADDR bd_addr, UINT8 *p_max_key_size,
+ tBTA_LE_KEY_TYPE *p_init_key,
+ tBTA_LE_KEY_TYPE *p_resp_key )
+{
+ BTIF_TRACE_ERROR0("##################################");
+ BTIF_TRACE_ERROR0("bta_dm_co_le_io_key_req: only setting max size to 16");
+ BTIF_TRACE_ERROR0("##################################");
+ *p_max_key_size = 16;
+ *p_init_key = *p_resp_key =
+ (BTA_LE_KEY_PENC|BTA_LE_KEY_PID|BTA_LE_KEY_PCSRK|BTA_LE_KEY_LENC|BTA_LE_KEY_LID|BTA_LE_KEY_LCSRK);
+}
+
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+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)
+{
+ BTIF_TRACE_ERROR0("##################################");
+ BTIF_TRACE_ERROR0("bta_dm_co_ble_load_local_keys: TBD Load local keys if any are persisted");
+ BTIF_TRACE_ERROR0("##################################");
+}
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+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 )
+{
+ /* if OOB is not supported, this call-out function does not need to do anything
+ * otherwise, look for the OOB data associated with the address and set *p_oob_data accordingly
+ * If the answer can not be obtained right away,
+ * set *p_oob_data to BTA_OOB_UNKNOWN and call bta_dm_ci_io_req() when the answer is available */
+
+ /* *p_auth_req by default is FALSE for devices with NoInputNoOutput; TRUE for other devices. */
+ BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_auth_req=%d ble_authereq=%d", *p_auth_req, bte_appl_cfg.ble_auth_req);
+ BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_io_cap=%d ble_io_cap=%d", *p_io_cap, bte_appl_cfg.ble_io_cap);
+ BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_init_key=%d ble_init_key=%d", *p_init_key, bte_appl_cfg.ble_init_key);
+ BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_resp_key=%d ble_resp_key=%d", *p_resp_key, bte_appl_cfg.ble_resp_key );
+ BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_max_key_size=%d ble_max_key_size=%d", *p_max_key_size, bte_appl_cfg.ble_max_key_size );
+
+ *p_oob_data = FALSE;
+ if (bte_appl_cfg.ble_auth_req)
+ *p_auth_req = bte_appl_cfg.ble_auth_req | (bte_appl_cfg.ble_auth_req & 0x04) | ((*p_auth_req) & 0x04);
+
+ if (bte_appl_cfg.ble_io_cap <=4)
+ *p_io_cap = bte_appl_cfg.ble_io_cap;
+
+ if (bte_appl_cfg.ble_init_key<=7)
+ *p_init_key = bte_appl_cfg.ble_init_key;
+
+ if (bte_appl_cfg.ble_resp_key<=7)
+ *p_resp_key = bte_appl_cfg.ble_resp_key;
+
+ if (bte_appl_cfg.ble_max_key_size<=16)
+ *p_max_key_size = bte_appl_cfg.ble_max_key_size;
+
+}
+
+
+#endif
+
diff --git a/btif/co/bta_fs_co.c b/btif/co/bta_fs_co.c
new file mode 100644
index 0000000..ffc146b
--- /dev/null
+++ b/btif/co/bta_fs_co.c
@@ -0,0 +1,1181 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <time.h>
+#include <limits.h>
+#include "gki.h"
+#include "bta_fs_co.h"
+#include "bta_fs_ci.h"
+#include <inttypes.h>
+
+#ifndef AID_SYSTEM
+#define AID_SYSTEM 1000
+#define AID_BLUETOOTH 1002
+#define AID_SDCARD_RW 1015
+#define AID_MISC 9998
+#endif
+
+#define FAT_FS 0x4d44
+const unsigned short BT_UID= AID_BLUETOOTH;
+const unsigned short BT_GID= AID_BLUETOOTH;
+
+/* enable additional debugging traces that should be compiled out by default! */
+#ifndef BTA_FS_DEBUG
+#define BTA_FS_DEBUG TRUE
+#define LOG_TAG "BTA_FS_CO"
+#define LOGI(format, ...) fprintf (stdout, LOG_TAG format"\n", ## __VA_ARGS__)
+#endif
+
+#if (defined BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+extern const tBTA_PBS_CFG bta_pbs_cfg;
+#endif
+
+
+
+static int del_path (const char *path)
+{
+ DIR *dir;
+ struct dirent *de;
+ int ret = 0;
+ char nameBuffer[PATH_MAX] = {0};
+ struct stat statBuffer;
+ BTIF_TRACE_DEBUG1("in del_path for path:%s", path);
+ dir = opendir(path);
+
+ if (dir == NULL) {
+ BTIF_TRACE_DEBUG1("opendir failed on path:%s", path);
+ return -1;
+ }
+
+ char *filenameOffset;
+
+ strncpy(nameBuffer, path, PATH_MAX - 1);
+ strcat(nameBuffer, "/");
+ int nameLen = strlen(nameBuffer);
+ filenameOffset = nameBuffer + nameLen;
+
+ for (;;) {
+ de = readdir(dir);
+
+ if (de == NULL) {
+ BTIF_TRACE_DEBUG1("readdir failed for path:%s", path);
+ //ret = -1;
+ break;
+ }
+
+ if (0 == strcmp(de->d_name, ".") || 0 == strcmp(de->d_name, ".."))
+ continue;
+
+ if((int)strlen(de->d_name) > PATH_MAX - nameLen) {
+ BTIF_TRACE_DEBUG1("d_name len:%d is too big", strlen(de->d_name));
+ ret = -1;
+ break;
+ }
+
+ strcpy(filenameOffset, de->d_name);
+
+ ret = lstat (nameBuffer, &statBuffer);
+
+ if (ret != 0) {
+ BTIF_TRACE_DEBUG1("lstat failed for path:%s", nameBuffer);
+ break;
+ }
+
+ if(S_ISDIR(statBuffer.st_mode)) {
+
+ ret = del_path(nameBuffer);
+ if(ret != 0)
+ break;
+ } else {
+ ret = unlink(nameBuffer);
+ if (ret != 0) {
+ BTIF_TRACE_DEBUG1("unlink failed for path:%s", nameBuffer);
+ break;
+ }
+ }
+ }
+
+ closedir(dir);
+ if(ret == 0) {
+ ret = rmdir(path);
+ BTIF_TRACE_DEBUG2("rmdir return:%d for path:%s", ret, path);
+ }
+
+ return ret;
+
+}
+
+inline int getAccess(int accType, struct stat *buffer, char *p_path)
+{
+
+ struct statfs fsbuffer;
+ int idType;
+
+ if(! buffer)
+ return BTA_FS_CO_FAIL;
+
+ //idType= (buffer->st_uid== BT_UID) ? 1 : (buffer->st_uid== BT_GID) ? 2 : 3;
+ if(buffer->st_uid == BT_UID)
+ idType = 1;
+ else if(buffer->st_gid == BT_GID ||
+ buffer->st_gid == AID_SYSTEM ||
+ buffer->st_gid == AID_MISC ||
+ buffer->st_gid == AID_SDCARD_RW)
+ idType = 2;
+ else idType = 3;
+
+ if(statfs(p_path, &fsbuffer)==0)
+ {
+ if(fsbuffer.f_type == FAT_FS)
+ return BTA_FS_CO_OK;
+ }
+ else {
+ return BTA_FS_CO_FAIL;
+ }
+
+ switch(accType) {
+ case 4:
+ if(idType== 1) { //Id is User Id
+ if(buffer-> st_mode & S_IRUSR)
+ return BTA_FS_CO_OK;
+ }
+ else if(idType==2) { //Id is Group Id
+ if(buffer-> st_mode & S_IRGRP)
+ return BTA_FS_CO_OK;
+ }
+ else { //Id is Others
+ if(buffer-> st_mode & S_IROTH)
+ return BTA_FS_CO_OK;
+ }
+ break;
+
+ case 6:
+ if(idType== 1) { //Id is User Id
+ if((buffer-> st_mode & S_IRUSR) && (buffer-> st_mode & S_IWUSR))
+ return BTA_FS_CO_OK;
+ }
+ else if(idType==2) { //Id is Group Id
+ if((buffer-> st_mode & S_IRGRP) && (buffer-> st_mode & S_IWGRP))
+ return BTA_FS_CO_OK;
+ }
+ else { //Id is Others
+ if((buffer-> st_mode & S_IROTH) && (buffer-> st_mode & S_IWOTH))
+ return BTA_FS_CO_OK;
+ }
+ break;
+
+ default:
+ return BTA_FS_CO_OK;
+ }
+ BTIF_TRACE_DEBUG0("*************FTP- Access Failed **********");
+ return BTA_FS_CO_EACCES;
+}
+
+
+/*****************************************************************************
+** Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function bta_fs_convert_oflags
+**
+** Description This function converts the open flags from BTA into MFS.
+**
+** Returns BTA FS status value.
+**
+*******************************************************************************/
+int bta_fs_convert_bta_oflags(int bta_oflags)
+{
+ int oflags = 0; /* Initially read only */
+
+ /* Only one of these can be set: Read Only, Read/Write, or Write Only */
+ if (bta_oflags & BTA_FS_O_RDWR)
+ oflags |= O_RDWR;
+ else if (bta_oflags & BTA_FS_O_WRONLY)
+ oflags |= O_WRONLY;
+
+ /* OR in any other flags that are set by BTA */
+ if (bta_oflags & BTA_FS_O_CREAT)
+ oflags |= O_CREAT;
+
+ if (bta_oflags & BTA_FS_O_EXCL)
+ oflags |= O_EXCL;
+
+ if (bta_oflags & BTA_FS_O_TRUNC)
+ oflags |= O_TRUNC;
+
+ return (oflags);
+}
+
+
+
+/*******************************************************************************
+ **
+ ** Function btapp_fs_check_space
+ **
+ ** Description determines access and if there is enough space for given files size on given path
+ **
+ ** Parameters p_path - Fully qualified path and file name.
+ ** WARNING: file name is stripped off! so it must be present!
+ ** size - size of file to put (0 if unavailable or not applicable)
+ ** app_id - in case application specific treatement is required (e.g opp versus ftp)
+ ** Returns 0 if enough space, otherwise errno failure codes
+ **
+ *******************************************************************************/
+static int btapp_fs_check_space( const char *p_path, const UINT32 size, const UINT8 app_id )
+{
+
+ unsigned long long max_space;
+ struct statfs fs_buffer;
+ int err = 0;
+ char *p_dir;
+ char *p_end;
+
+ if(size==BTA_FS_LEN_UNKNOWN)
+ return 0;
+ /* fail silently in case of no memory. write will catch if not enough space */
+
+ if (NULL != (p_dir = (char *) GKI_getbuf(strlen(p_path) + 1)))
+ {
+ strcpy(p_dir, p_path);
+ if (NULL != (p_end = strrchr(p_dir, '/')))
+ {
+
+ *p_end = '\0';
+ /* get fs info and calculate available space. if not enough, the fs error EFBIG is returned */
+
+ if (0 == statfs(p_dir, &fs_buffer))
+ {
+
+ max_space = fs_buffer.f_bavail * fs_buffer.f_bsize;
+#if (BTA_FS_DEBUG==TRUE)
+ BTIF_TRACE_DEBUG2("btapp_fs_enough_space(file size: %d): (uint)max_size: %u", size, (UINT32)max_space);
+#endif
+ if (max_space < size)
+ err = EFBIG;
+ }
+ else
+ {
+ err = errno;
+ BTIF_TRACE_WARNING1("btapp_fs_enough_space(): statfs() failed with err: %d", err);
+ }
+ }
+ else
+ {
+ err = ENOENT;
+ }
+ GKI_freebuf(p_dir);
+ }
+ else
+ {
+ err = ENOMEM;
+ }
+ return err;
+
+} /* btapp_fs_check_access_space() */
+
+
+/*******************************************************************************
+**
+** 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().
+**
+*******************************************************************************/
+
+void bta_fs_co_open(const char *p_path, int oflags, UINT32 size, UINT16 evt,
+ UINT8 app_id)
+{
+
+ tBTA_FS_CO_STATUS status;
+ UINT32 file_size = 0;
+ struct stat file_stat;
+ int fd = -1;
+ int err = 0;
+
+ /* Convert BTA oflags into os specific flags */
+ oflags = bta_fs_convert_bta_oflags(oflags);
+
+ /* check available space in case of write access. oflags are in OS format! */
+ if (oflags & (O_RDWR|O_WRONLY))
+ {
+ err = btapp_fs_check_space(p_path, size, app_id);
+ }
+
+ if ( 0==err )
+ {
+ if ((fd = open(p_path, oflags | O_NONBLOCK, 0666)) >= 0)
+ {
+ if (fstat(fd, &file_stat) == 0)
+ {
+ file_size = file_stat.st_size;
+ if (oflags & O_CREAT)
+ {
+ fchown(fd, BT_UID, BT_GID);
+ BTIF_TRACE_DEBUG0("\n ******CHANGED OWNERSHIP SUCCESSFULLY**********");
+ }
+ }
+ }
+
+ else
+ {
+ err = errno;
+ }
+ }
+
+ BTIF_TRACE_DEBUG4("[CO] bta_fs_co_open: handle:%d err:%d, flags:%x, app id:%d",
+ fd, err, oflags, app_id);
+ BTIF_TRACE_DEBUG1("file=%s", p_path);
+
+ /* convert fs error into bta_fs err. erro is set by first call to enough space to a valid value
+ * and needs only updating in case of error. This reports correct failure to remote obex! */
+
+ switch (err)
+ {
+
+ case 0:
+ status = BTA_FS_CO_OK;
+ break;
+ case EACCES:
+ status = BTA_FS_CO_EACCES;
+ break;
+ case EFBIG: /* file to big for available fs space */
+ status = BTA_FS_CO_ENOSPACE;
+ break;
+ default:
+ status = BTA_FS_CO_FAIL;
+ break;
+ }
+ bta_fs_ci_open(fd, status, file_size, evt);
+}
+
+/*******************************************************************************
+**
+** 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 ]
+**
+*******************************************************************************/
+tBTA_FS_CO_STATUS bta_fs_co_close(int fd, UINT8 app_id)
+{
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
+ int err;
+
+ BTIF_TRACE_DEBUG2("[CO] bta_fs_co_close: handle:%d, app id:%d",
+ fd, app_id);
+ if (close (fd) < 0)
+ {
+ err = errno;
+ status = BTA_FS_CO_FAIL;
+ BTIF_TRACE_WARNING3("[CO] bta_fs_co_close: handle:%d error=%d app_id:%d", fd, err, app_id);
+ }
+
+ return (status);
+}
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+void bta_fs_co_read(int fd, UINT8 *p_buf, UINT16 nbytes, UINT16 evt, UINT8 ssn, UINT8 app_id)
+{
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
+ INT32 num_read;
+ int err;
+
+ if ((num_read = read (fd, p_buf, nbytes)) < 0)
+ {
+ err = errno;
+ status = BTA_FS_CO_FAIL;
+ BTIF_TRACE_WARNING3("[CO] bta_fs_co_read: handle:%d error=%d app_id:%d",
+ fd, err, app_id);
+ }
+ else if (num_read < nbytes)
+ status = BTA_FS_CO_EOF;
+
+ bta_fs_ci_read(fd, (UINT16)num_read, status, evt);
+}
+
+/*******************************************************************************
+**
+** 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,
+**
+*******************************************************************************/
+void bta_fs_co_write(int fd, const UINT8 *p_buf, UINT16 nbytes, UINT16 evt,
+ UINT8 ssn, UINT8 app_id)
+{
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
+ INT32 num_written;
+ int err=0;
+
+ if ((num_written = write (fd, p_buf, nbytes)) < 0)
+ {
+ err = errno;
+ status = BTA_FS_CO_FAIL;
+ }
+/* BTIF_TRACE_DEBUG3("[CO] bta_fs_co_write: handle:%d error=%d, num_written:%d", fd, err, num_written);*/
+
+ bta_fs_ci_write(fd, status, evt);
+}
+
+/*******************************************************************************
+**
+** 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.
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_fs_co_seek (int fd, INT32 offset, INT16 origin, UINT8 app_id)
+{
+ lseek(fd, offset, origin);
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_co_access
+**
+** Description This function is called to check the existence of
+** a file or directory, and return whether or not it is a
+** directory or length of the file.
+**
+** 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]
+**
+*******************************************************************************/
+tBTA_FS_CO_STATUS bta_fs_co_access(const char *p_path, int mode, BOOLEAN *p_is_dir,
+ UINT8 app_id)
+{
+ int err;
+ int os_mode = 0;
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
+ struct stat buffer;
+
+ #if (TRUE==BTA_FS_DEBUG)
+ LOGI("***********CHECKING ACCESS TO = %s", p_path);
+ #endif
+
+ #if (defined BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+ if (app_id == UI_PBS_ID)
+ {
+
+ *p_is_dir = TRUE;
+
+ #if (TRUE==BTA_FS_DEBUG)
+ LOGI("***********SUPPORTED REPO = %d", bta_pbs_cfg.supported_repositories);
+ #endif
+ //Check if SIM contact requested, and if so if it's supported.
+ //If not, return error!
+ if (strstr(p_path,"SIM1") && !(bta_pbs_cfg.supported_repositories & 0x2)) {
+ LOGI("***********RETURNING FAIL!");
+ return BTA_FS_CO_FAIL;
+ }
+
+ #if (TRUE==BTA_FS_DEBUG)
+ LOGI("***********RETURNING success!");
+ #endif
+ return (status);
+ }
+ #endif
+
+
+ *p_is_dir = FALSE;
+
+ if (mode == BTA_FS_ACC_RDWR)
+ os_mode = 6;
+ else if (mode == BTA_FS_ACC_READ)
+ os_mode = 4;
+
+ if (stat(p_path, &buffer) == 0)
+ {
+ /* Determine if the object is a file or directory */
+ if (S_ISDIR(buffer.st_mode))
+ *p_is_dir = TRUE;
+ }
+ else
+ {
+ BTIF_TRACE_DEBUG0("stat() failed! ");
+ return BTA_FS_CO_FAIL;
+ }
+
+ status=getAccess (os_mode, &buffer, (char*)p_path);
+ return (status);
+}
+
+/*******************************************************************************
+**
+** 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]
+**
+*******************************************************************************/
+tBTA_FS_CO_STATUS bta_fs_co_mkdir(const char *p_path, UINT8 app_id)
+{
+ int err;
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
+
+ if ((mkdir (p_path, 0666)) != 0)
+ {
+ err = errno;
+ status = BTA_FS_CO_FAIL;
+ BTIF_TRACE_WARNING3("[CO] bta_fs_co_mkdir: error=%d, path [%s] app_id:%d",
+ err, p_path, app_id);
+ }
+ return (status);
+}
+
+/*******************************************************************************
+**
+** 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]
+**
+*******************************************************************************/
+tBTA_FS_CO_STATUS bta_fs_co_rmdir(const char *p_path, UINT8 app_id)
+{
+ int err, path_len;
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
+ struct stat buffer;
+ char *dirName, *tmp = NULL;
+
+ path_len = strlen( p_path )+1;
+ BTIF_TRACE_DEBUG2( "bta_fs_co_rmdir( app_id: %d ): path_len: %d", app_id, path_len );
+#if (TRUE==BTA_FS_DEBUG)
+ BTIF_TRACE_DEBUG1( "bta_fs_co_rmdir():path_len: %d, p_path", app_id );
+ BTIF_TRACE_DEBUG0( p_path );
+#endif
+
+ /* allocate a temp buffer for path with 0 char. make sure not to crash if path is too big! */
+ dirName = (char*) calloc(1, path_len+1);
+ if ( NULL != dirName )
+ {
+ strcpy( dirName, p_path );
+ }
+ else
+ {
+ BTIF_TRACE_WARNING2( "bta_fs_co_rmdir( app_id: %d ) for path_len: %d::out of memory",
+ app_id, path_len );
+ return BTA_FS_CO_FAIL;
+ }
+
+ if (NULL!= (tmp = strrchr(dirName, '/')))
+ {
+ *tmp = '\0';
+ }
+ if (stat(dirName, &buffer) == 0)
+ {
+ status = getAccess(6, &buffer, dirName);
+ }
+ else
+ {
+ free(dirName);
+#if (TRUE==BTA_FS_DEBUG)
+ BTIF_TRACE_WARNING0( "bta_fs_co_rmdir()::stat(dirName) failed" );
+#endif
+ return BTA_FS_CO_FAIL;
+ }
+
+ free(dirName);
+ if (status != BTA_FS_CO_OK)
+ {
+#if (TRUE==BTA_FS_DEBUG)
+ BTIF_TRACE_WARNING0( "bta_fs_co_rmdir()::getAccess(dirName) FAILED");
+#endif
+ return status;
+ }
+
+ if (stat(p_path, &buffer) == 0)
+ {
+ status = getAccess(6, &buffer, (char*)p_path);
+ }
+ else
+ {
+#if (TRUE==BTA_FS_DEBUG)
+ BTIF_TRACE_WARNING0( "bta_fs_co_rmdir()::stat(p_path) FAILED");
+#endif
+ return BTA_FS_CO_FAIL;
+ }
+
+ if (status != BTA_FS_CO_OK)
+ {
+#if (TRUE==BTA_FS_DEBUG)
+ BTIF_TRACE_DEBUG0( "bta_fs_co_rmdir()::getAccess(p_path) FAILED");
+#endif
+ return status;
+ }
+ //if ((rmdir (p_path)) != 0)
+ if (del_path(p_path) != 0)
+ {
+ err = errno;
+ BTIF_TRACE_WARNING1( "bta_fs_co_rmdir():rmdir/del_path FAILED with err: %d", err );
+ if (err == EACCES)
+ status = BTA_FS_CO_EACCES;
+ else if (err == ENOTEMPTY)
+ status = BTA_FS_CO_ENOTEMPTY;
+ else
+ status = BTA_FS_CO_FAIL;
+ }
+ return (status);
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_co_unlink
+**
+** Description This function is called 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]
+**
+*******************************************************************************/
+tBTA_FS_CO_STATUS bta_fs_co_unlink(const char *p_path, UINT8 app_id)
+{
+ BTIF_TRACE_DEBUG0("bta_fs_co_unlink");
+ int err;
+ tBTA_FS_CO_STATUS status = BTA_FS_CO_OK;
+ char *dirName, *tmp=NULL;
+ struct stat buffer;
+
+ if(! p_path)
+ return BTA_FS_CO_FAIL;
+
+ /* buffer needs to be NULL terminated - so add one more byte to be zero'd out */
+#if 0
+ dirName= (char*) calloc(1, strlen(p_path)); /* <--- this can cause problems */
+#else
+ dirName= (char*) calloc(1, strlen(p_path) + 1);
+#endif
+
+ strncpy(dirName, p_path, strlen(p_path));
+ if((tmp=strrchr(dirName, '/')))
+ {
+ *tmp='\0';
+ }
+ if (stat(dirName, &buffer) == 0)
+ {
+ status=getAccess (6, &buffer, dirName);
+ free(dirName);
+ }
+ else
+ {
+ BTIF_TRACE_DEBUG0("stat() failed! ");
+ free(dirName);
+ return BTA_FS_CO_FAIL;
+ }
+
+ if(status!= BTA_FS_CO_OK)
+ return status;
+
+ if ((unlink (p_path)) != 0)
+ {
+ err = errno;
+ if (err == EACCES)
+ status = BTA_FS_CO_EACCES;
+ else
+ status = BTA_FS_CO_FAIL;
+ }
+ return (status);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_fs_co_getdirentry
+**
+** Description This function is called to get a directory entry for the
+** specified p_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
+**
+*******************************************************************************/
+void bta_fs_co_getdirentry(const char *p_path, BOOLEAN first_item,
+ tBTA_FS_DIRENTRY *p_entry, UINT16 evt, UINT8 app_id)
+{
+ tBTA_FS_CO_STATUS co_status = BTA_FS_CO_FAIL;
+ int status = -1; /* '0' - success, '-1' - fail */
+ struct tm *p_tm;
+ DIR *dir;
+ struct dirent *dirent;
+ struct stat buf;
+ char fullname[500];
+
+ BTIF_TRACE_DEBUG0("Entered bta_fs_co_getdirentry");
+
+ /* First item is to be retrieved */
+ if (first_item)
+ {
+ BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: path = %s", p_path);
+
+ dir = opendir(p_path);
+ if(dir == NULL)
+ {
+ BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dir is NULL so error out with errno=%d", errno);
+ co_status = BTA_FS_CO_EODIR;
+ bta_fs_ci_direntry(co_status, evt);
+ return;
+ }
+
+ BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dir = %p", dir);
+ if((dirent = readdir(dir)) != NULL)
+ {
+ p_entry->refdata = (UINT32) dir; /* Save this for future searches */
+ status = 0;
+ BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dirent = %p", dirent);
+ }
+ else
+ {
+ BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dirent = %p", dirent);
+ /* Close the search if there are no more items */
+ closedir( (DIR*) p_entry->refdata);
+ co_status = BTA_FS_CO_EODIR;
+ }
+ }
+ else /* Get the next entry based on the p_ref data from previous search */
+ {
+ if ((dirent = readdir((DIR*)p_entry->refdata)) == NULL)
+ {
+ /* Close the search if there are no more items */
+ closedir( (DIR*) p_entry->refdata);
+ co_status = BTA_FS_CO_EODIR;
+ BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dirent = %p", dirent);
+ }
+ else
+ {
+ BTIF_TRACE_DEBUG1("bta_fs_co_getdirentry: dirent = %p", dirent);
+ status = 0;
+ }
+ }
+
+ if (status == 0)
+ {
+ BTIF_TRACE_DEBUG0("bta_fs_co_getdirentry: status = 0");
+
+ sprintf(fullname, "%s/%s", p_path, dirent->d_name);
+
+ /* Load new values into the return structure (refdata is left untouched) */
+ if (stat(fullname, &buf) == 0) {
+ p_entry->filesize = buf.st_size;
+ p_entry->mode = 0; /* Default is normal read/write file access */
+
+ if (S_ISDIR(buf.st_mode))
+ p_entry->mode |= BTA_FS_A_DIR;
+ else
+ p_entry->mode |= BTA_FS_A_RDONLY;
+
+ strcpy(p_entry->p_name, dirent->d_name);
+#if 0
+ fprintf(stderr, "bta_fs_co_getdirentry(): %s %9d %d\n",
+ dirent->d_name,
+ buf.st_size,
+ p_entry->mode);
+#endif
+ p_tm = localtime((const time_t*)&buf.st_mtime);
+ if (p_tm != NULL)
+ {
+ sprintf(p_entry->crtime, "%04d%02d%02dT%02d%02d%02dZ",
+ p_tm->tm_year + 1900, /* Base Year ISO 6201 */
+ p_tm->tm_mon + 1, /* month starts at 0 */
+ p_tm->tm_mday,
+ p_tm->tm_hour,
+ p_tm->tm_min,
+ p_tm->tm_sec);
+ }
+ else
+ p_entry->crtime[0] = '\0'; /* No valid time */
+#if 0
+ fprintf(stderr, "bta_fs_co_getdirentry(): %s %9d %d %s\n",
+ dirent->d_name,
+ p_entry->filesize,
+ p_entry->mode,
+ p_entry->crtime);
+#endif
+ co_status = BTA_FS_CO_OK;
+ } else {
+ BTIF_TRACE_WARNING0("stat() failed! ");
+ co_status = BTA_FS_CO_EACCES;
+ }
+ }
+ BTIF_TRACE_DEBUG0("bta_fs_co_getdirentry: calling bta_fs_ci_getdirentry");
+
+ bta_fs_ci_direntry(co_status, evt);
+}
+
+
+
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+void bta_fs_co_setdir(const char *p_path, UINT8 app_id)
+{
+ BTIF_TRACE_DEBUG2("Entered %s. New path: %s", __FUNCTION__, p_path);
+}
+
+/*******************************************************************************
+** OBEX14 Reliable Session not supported. Stub associated callouts.
+******************************************************************************/
+
+/*******************************************************************************
+**
+** 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().
+**
+*******************************************************************************/
+void bta_fs_co_resume(UINT16 evt, UINT8 app_id)
+{
+ BTIF_TRACE_WARNING0("[CO] bta_fs_co_resume - NOT implemented");
+}
+
+/*******************************************************************************
+**
+** 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]
+**
+*******************************************************************************/
+void bta_fs_co_set_perms(const char *p_src_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id)
+{
+ BTIF_TRACE_WARNING0("[CO] bta_fs_co_set_perms - NOT implemented");
+}
+
+/*******************************************************************************
+**
+** 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]
+**
+*******************************************************************************/
+void bta_fs_co_rename(const char *p_src_path, const char *p_dest_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id)
+{
+ BTIF_TRACE_WARNING0("[CO] bta_fs_co_rename - NOT implemented");
+}
+
+/*******************************************************************************
+**
+** 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]
+**
+*******************************************************************************/
+void bta_fs_co_copy(const char *p_src_path, const char *p_dest_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id)
+{
+ BTIF_TRACE_WARNING0("[CO] bta_fs_co_copy - NOT implemented");
+}
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+void bta_fs_co_resume_op(UINT32 offset, UINT16 evt, UINT8 app_id)
+{
+ BTIF_TRACE_WARNING0("[CO] bta_fs_co_resume_op - NOT implemented");
+}
+
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+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)
+{
+ BTIF_TRACE_WARNING0("[CO] bta_fs_co_session_info - NOT implemented");
+}
+
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+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)
+{
+ BTIF_TRACE_WARNING0("[CO] bta_fs_co_suspend - NOT implemented");
+}
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+void bta_fs_co_sess_ssn(int fd, UINT8 ssn, UINT8 app_id)
+{
+ BTIF_TRACE_WARNING0("[CO] bta_fs_co_suspend - NOT implemented");
+}
+
diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c
new file mode 100644
index 0000000..81414d2
--- /dev/null
+++ b/btif/co/bta_hh_co.c
@@ -0,0 +1,276 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+//#if (defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE))
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <linux/uhid.h>
+#include "btif_hh.h"
+#include "bta_api.h"
+#include "bta_hh_api.h"
+
+
+
+const char *dev_path = "/dev/uhid";
+
+
+/*Internal function to perform UHID write and error checking*/
+static int uhid_write(int fd, const struct uhid_event *ev)
+{
+ ssize_t ret;
+ ret = write(fd, ev, sizeof(*ev));
+ if (ret < 0){
+ int rtn = -errno;
+ APPL_TRACE_ERROR2("%s: Cannot write to uhid:%s",__FUNCTION__,strerror(errno));
+ return rtn;
+ } else if (ret != sizeof(*ev)) {
+ APPL_TRACE_ERROR3("%s: Wrong size written to uhid: %ld != %lu",
+ __FUNCTION__, ret, sizeof(*ev));
+ return -EFAULT;
+ } else {
+ return 0;
+ }
+}
+
+void bta_hh_co_destroy(int fd)
+{
+ struct uhid_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.type = UHID_DESTROY;
+ uhid_write(fd, &ev);
+ close(fd);
+}
+
+int bta_hh_co_write(int fd, UINT8* rpt, UINT16 len)
+{
+ APPL_TRACE_DEBUG0("bta_hh_co_data: UHID write");
+ struct uhid_event ev;
+ memset(&ev, 0, sizeof(ev));
+ ev.type = UHID_INPUT;
+ ev.u.input.size = len;
+ if(len > sizeof(ev.u.input.data)){
+ APPL_TRACE_WARNING1("%s:report size greater than allowed size",__FUNCTION__);
+ return -1;
+ }
+ memcpy(ev.u.input.data, rpt, len);
+ return uhid_write(fd, &ev);
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hh_co_open
+**
+** Description When connection is opened, this call-out function is executed
+** by HH to do platform specific initialization.
+**
+** Returns void.
+*******************************************************************************/
+void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class, tBTA_HH_ATTR_MASK attr_mask,
+ UINT8 app_id)
+{
+ UINT32 i;
+ btif_hh_device_t *p_dev = NULL;
+
+ if (dev_handle == BTA_HH_INVALID_HANDLE) {
+ APPL_TRACE_WARNING2("%s: Oops, dev_handle (%d) is invalid...", __FUNCTION__, dev_handle);
+ return;
+ }
+
+ for (i = 0; i < BTIF_HH_MAX_HID; i++) {
+ p_dev = &btif_hh_cb.devices[i];
+ if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) {
+ // We found a device with the same handle. Must be a device reconnected.
+ APPL_TRACE_WARNING2("%s: Found an existing device with the same handle "
+ "dev_status = %d",__FUNCTION__,
+ p_dev->dev_status);
+ APPL_TRACE_WARNING6("%s: bd_addr = [%02X:%02X:%02X:%02X:%02X:]", __FUNCTION__,
+ p_dev->bd_addr.address[0], p_dev->bd_addr.address[1], p_dev->bd_addr.address[2],
+ p_dev->bd_addr.address[3], p_dev->bd_addr.address[4]);
+ APPL_TRACE_WARNING4("%s: attr_mask = 0x%04x, sub_class = 0x%02x, app_id = %d",
+ __FUNCTION__, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id);
+
+ if(p_dev->fd<0) {
+ p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC);
+ if (p_dev->fd < 0){
+ APPL_TRACE_ERROR2("%s: Error: failed to open uhid, err:%s",
+ __FUNCTION__,strerror(errno));
+ }else
+ APPL_TRACE_DEBUG2("%s: uhid fd = %d", __FUNCTION__, p_dev->fd);
+ }
+
+ break;
+ }
+ p_dev = NULL;
+ }
+
+ if (p_dev == NULL) {
+ // Did not find a device reconnection case. Find an empty slot now.
+ for (i = 0; i < BTIF_HH_MAX_HID; i++) {
+ if (btif_hh_cb.devices[i].dev_status == BTHH_CONN_STATE_UNKNOWN) {
+ p_dev = &btif_hh_cb.devices[i];
+ p_dev->dev_handle = dev_handle;
+ p_dev->attr_mask = attr_mask;
+ p_dev->sub_class = sub_class;
+ p_dev->app_id = app_id;
+
+ btif_hh_cb.device_num++;
+ // This is a new device,open the uhid driver now.
+ p_dev->fd = open(dev_path, O_RDWR | O_CLOEXEC);
+ if (p_dev->fd < 0){
+ APPL_TRACE_ERROR2("%s: Error: failed to open uhid, err:%s",
+ __FUNCTION__,strerror(errno));
+ }else
+ APPL_TRACE_DEBUG2("%s: uhid fd = %d", __FUNCTION__, p_dev->fd);
+
+
+ break;
+ }
+ }
+ }
+
+ if (p_dev == NULL) {
+ APPL_TRACE_ERROR1("%s: Error: too many HID devices are connected", __FUNCTION__);
+ return;
+ }
+
+ p_dev->dev_status = BTHH_CONN_STATE_CONNECTED;
+ APPL_TRACE_DEBUG2("%s: Return device status %d", __FUNCTION__, p_dev->dev_status);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hh_co_close
+**
+** Description When connection is closed, this call-out function is executed
+** by HH to do platform specific finalization.
+**
+** Parameters dev_handle - device handle
+** app_id - application id
+**
+** Returns void.
+*******************************************************************************/
+void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id)
+{
+ APPL_TRACE_WARNING3("%s: dev_handle = %d, app_id = %d", __FUNCTION__, dev_handle, app_id);
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hh_co_data
+**
+** Description This function is executed by BTA when HID host receive a data
+** report.
+**
+** Parameters dev_handle - device handle
+** *p_rpt - pointer to the report data
+** len - length of report data
+** mode - Hid host Protocol Mode
+** sub_clas - Device Subclass
+** app_id - application id
+**
+** Returns void
+*******************************************************************************/
+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)
+{
+ btif_hh_device_t *p_dev;
+
+ APPL_TRACE_DEBUG6("%s: dev_handle = %d, subclass = 0x%02X, mode = %d, "
+ "ctry_code = %d, app_id = %d",
+ __FUNCTION__, dev_handle, sub_class, mode, ctry_code, app_id);
+
+ p_dev = btif_hh_find_connected_dev_by_handle(dev_handle);
+ if (p_dev == NULL) {
+ APPL_TRACE_WARNING2("%s: Error: unknown HID device handle %d", __FUNCTION__, dev_handle);
+ return;
+ }
+ // Send the HID report to the kernel.
+ if (p_dev->fd >= 0) {
+ bta_hh_co_write(p_dev->fd, p_rpt, len);
+ }else {
+ APPL_TRACE_WARNING3("%s: Error: fd = %d, len = %d", __FUNCTION__, p_dev->fd, len);
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hh_co_send_hid_info
+**
+** Description This function is called in btif_hh.c to process DSCP received.
+**
+** Parameters dev_handle - device handle
+** dscp_len - report descriptor length
+** *p_dscp - report descriptor
+**
+** Returns void
+*******************************************************************************/
+void bta_hh_co_send_hid_info(btif_hh_device_t *p_dev, char *dev_name, UINT16 vendor_id,
+ UINT16 product_id, UINT16 version, UINT8 ctry_code,
+ int dscp_len, UINT8 *p_dscp)
+{
+ int result;
+ struct uhid_event ev;
+
+ if (p_dev->fd < 0) {
+ APPL_TRACE_WARNING3("%s: Error: fd = %d, dscp_len = %d", __FUNCTION__, p_dev->fd, dscp_len);
+ return;
+ }
+
+ APPL_TRACE_WARNING4("%s: fd = %d, name = [%s], dscp_len = %d", __FUNCTION__,
+ p_dev->fd, dev_name, dscp_len);
+ APPL_TRACE_WARNING5("%s: vendor_id = 0x%04x, product_id = 0x%04x, version= 0x%04x,"
+ "ctry_code=0x%02x",__FUNCTION__,
+ vendor_id, product_id,
+ version, ctry_code);
+
+//Create and send hid descriptor to kernel
+ memset(&ev, 0, sizeof(ev));
+ ev.type = UHID_CREATE;
+ strncpy((char*)ev.u.create.name, dev_name, sizeof(ev.u.create.name) - 1);
+ ev.u.create.rd_size = dscp_len;
+ ev.u.create.rd_data = p_dscp;
+ ev.u.create.bus = BUS_BLUETOOTH;
+ ev.u.create.vendor = vendor_id;
+ ev.u.create.product = product_id;
+ ev.u.create.version = version;
+ ev.u.create.country = ctry_code;
+ result = uhid_write(p_dev->fd, &ev);
+
+ APPL_TRACE_WARNING4("%s: fd = %d, dscp_len = %d, result = %d", __FUNCTION__,
+ p_dev->fd, dscp_len, result);
+
+ if (result) {
+ APPL_TRACE_WARNING2("%s: Error: failed to send DSCP, result = %d", __FUNCTION__, result);
+
+ /* The HID report descriptor is corrupted. Close the driver. */
+ close(p_dev->fd);
+ p_dev->fd = -1;
+ }
+}
+
+
diff --git a/btif/co/bta_hl_co.c b/btif/co/bta_hl_co.c
new file mode 100644
index 0000000..a7a9061
--- /dev/null
+++ b/btif/co/bta_hl_co.c
@@ -0,0 +1,459 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * This is the implementation file for the HeaLth device profile (HL)
+ * subsystem call-out functions.
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <time.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <cutils/sockets.h>
+#include <cutils/log.h>
+#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_ci.h"
+#include "btif_hl.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
+**
+*******************************************************************************/
+BOOLEAN bta_hl_co_get_num_of_mdep(UINT8 app_id, UINT8 *p_num_of_mdep)
+{
+ UINT8 app_idx;
+ BOOLEAN success = FALSE;
+
+ if (btif_hl_find_app_idx(app_id, &app_idx))
+ {
+ *p_num_of_mdep = p_btif_hl_cb->acb[app_idx].sup_feature.num_of_mdeps;
+ success = TRUE;
+ }
+
+
+ BTIF_TRACE_DEBUG3("%s success=%d num_mdeps=%d",
+ __FUNCTION__, success, *p_num_of_mdep );
+ return success;
+}
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+BOOLEAN bta_hl_co_advrtise_source_sdp(UINT8 app_id)
+{
+ BOOLEAN advertize_source_sdp=FALSE;
+ UINT8 app_idx;
+
+ if (btif_hl_find_app_idx(app_id, &app_idx))
+ {
+ advertize_source_sdp = p_btif_hl_cb->acb[app_idx].sup_feature.advertize_source_sdp;
+ }
+
+
+ BTIF_TRACE_DEBUG2("%s advertize_flag=%d", __FUNCTION__, advertize_source_sdp );
+
+ return advertize_source_sdp;
+}
+/*******************************************************************************
+**
+** 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
+*******************************************************************************/
+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)
+{
+ UINT8 idx ;
+ UINT8 app_idx;
+ BOOLEAN success = FALSE;
+
+ BTIF_TRACE_DEBUG4("%s app_id=%d mdep_idx=%d mdep_id=%d",
+ __FUNCTION__, app_id,mdep_idx,mdep_id );
+
+ if (btif_hl_find_app_idx(app_id, &app_idx))
+ {
+ idx = mdep_idx -1;
+ p_btif_hl_cb->acb[app_idx].sup_feature.mdep[idx].mdep_id = mdep_id;
+ memcpy(p_mdep_cfg,
+ &p_btif_hl_cb->acb[app_idx].sup_feature.mdep[idx].mdep_cfg,
+ sizeof(tBTA_HL_MDEP_CFG));
+
+ success = TRUE;
+ }
+
+ BTIF_TRACE_DEBUG4("%s success=%d mdep_idx=%d mdep_id=%d",
+ __FUNCTION__, success, mdep_idx, mdep_id );
+
+ return success;
+}
+
+
+/*******************************************************************************
+**
+** Function bta_hl_co_get_echo_config
+**
+** Description This function is called to get the echo test
+** maximum APDU size configurations
+**
+** Parameters app_id - HDP application ID
+** p_echo_cfg (output) - pointer to the Echo test maximum APDU size
+** configuration
+**
+** Returns Bloolean - TRUE success
+*******************************************************************************/
+BOOLEAN bta_hl_co_get_echo_config(UINT8 app_id,
+ tBTA_HL_ECHO_CFG *p_echo_cfg)
+{
+ UINT8 app_idx;
+ BOOLEAN success = FALSE;
+ btif_hl_app_cb_t *p_acb;
+ tBTA_HL_SUP_FEATURE *p_sup;
+
+ BTIF_TRACE_DEBUG2("%s app_id=%d",__FUNCTION__, app_id );
+
+ if (btif_hl_find_app_idx(app_id, &app_idx))
+ {
+ p_acb = BTIF_HL_GET_APP_CB_PTR(app_idx);
+ p_sup = &p_acb->sup_feature;
+ p_echo_cfg->max_rx_apdu_size = p_sup->echo_cfg.max_rx_apdu_size;
+ p_echo_cfg->max_tx_apdu_size = p_sup->echo_cfg.max_tx_apdu_size;
+ success = TRUE;
+ }
+
+ BTIF_TRACE_DEBUG4("%s success=%d max tx_size=%d rx_size=%d",
+ __FUNCTION__, success, p_echo_cfg->max_tx_apdu_size,
+ p_echo_cfg->max_rx_apdu_size );
+
+ return success;
+}
+
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+void bta_hl_co_save_mdl(UINT8 app_id, UINT8 item_idx, tBTA_HL_MDL_CFG *p_mdl_cfg )
+{
+
+ BTIF_TRACE_DEBUG6("%s app_id=%d, item_idx=%d active=%d mdl_id=%d time=%d",
+ __FUNCTION__, app_id, item_idx,
+ p_mdl_cfg->active,
+ p_mdl_cfg->mdl_id,
+ p_mdl_cfg->time);
+
+
+ btif_hl_save_mdl_cfg(app_id, item_idx, 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
+**
+*******************************************************************************/
+void bta_hl_co_delete_mdl(UINT8 app_id, UINT8 item_idx)
+{
+
+
+ BTIF_TRACE_DEBUG3("%s app_id=%d, item_idx=%d", __FUNCTION__, app_id, item_idx);
+
+ btif_hl_delete_mdl_cfg(app_id, item_idx);
+
+
+}
+
+/*******************************************************************************
+**
+** Function bta_hl_co_get_mdl_config
+**
+** Description This function is called to get the MDL configuration
+** from the 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
+**
+**
+*******************************************************************************/
+BOOLEAN bta_hl_co_load_mdl_config (UINT8 app_id, UINT8 buffer_size,
+ tBTA_HL_MDL_CFG *p_mdl_buf )
+{
+ BOOLEAN result = TRUE;
+ UINT8 i;
+ tBTA_HL_MDL_CFG *p;
+
+ BTIF_TRACE_DEBUG3("%s app_id=%d, num_items=%d",
+ __FUNCTION__, app_id, buffer_size);
+
+ if (buffer_size > BTA_HL_NUM_MDL_CFGS)
+ {
+ result = FALSE;
+ return result;
+ }
+ result = btif_hl_load_mdl_config(app_id, buffer_size, p_mdl_buf);
+
+ if (result)
+ {
+ for (i=0, p=p_mdl_buf; i<buffer_size; i++, p++ )
+ {
+ if (p->active)
+ {
+ BTIF_TRACE_DEBUG6("i=%d mdl_id=0x%x dch_mode=%d local mdep_role=%d mdep_id=%d mtu=%d",
+ i, p->mdl_id, p->dch_mode, p->local_mdep_role, p->local_mdep_role, p->mtu);
+ }
+ }
+ }
+
+ BTIF_TRACE_DEBUG3("%s success=%d num_items=%d", __FUNCTION__, result, buffer_size);
+
+ return result;
+}
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+void bta_hl_co_get_tx_data (UINT8 app_id, tBTA_HL_MDL_HANDLE mdl_handle,
+ UINT16 buf_size, UINT8 *p_buf, UINT16 evt)
+{
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ btif_hl_mdl_cb_t *p_dcb;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
+
+ BTIF_TRACE_DEBUG4("%s app_id=%d mdl_handle=0x%x buf_size=%d",
+ __FUNCTION__, app_id, mdl_handle, buf_size);
+
+ if (btif_hl_find_mdl_idx_using_handle(mdl_handle, &app_idx, &mcl_idx, &mdl_idx))
+ {
+ p_dcb = BTIF_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+ if (p_dcb->tx_size <= buf_size )
+ {
+ memcpy(p_buf, p_dcb->p_tx_pkt, p_dcb->tx_size);
+ btif_hl_free_buf((void **) &p_dcb->p_tx_pkt);
+ p_dcb->tx_size = 0;
+ status = BTA_HL_STATUS_OK;
+ }
+ }
+
+
+ bta_hl_ci_get_tx_data(mdl_handle, status, 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
+**
+*******************************************************************************/
+void bta_hl_co_put_rx_data (UINT8 app_id, tBTA_HL_MDL_HANDLE mdl_handle,
+ UINT16 data_size, UINT8 *p_data, UINT16 evt)
+{
+ UINT8 app_idx, mcl_idx, mdl_idx;
+ btif_hl_mdl_cb_t *p_dcb;
+ tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
+ int r;
+ BTIF_TRACE_DEBUG4("%s app_id=%d mdl_handle=0x%x data_size=%d",
+ __FUNCTION__,app_id, mdl_handle, data_size);
+
+ if (btif_hl_find_mdl_idx_using_handle(mdl_handle, &app_idx, &mcl_idx, &mdl_idx))
+ {
+ p_dcb = BTIF_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+ if ((p_dcb->p_rx_pkt = (UINT8 *)btif_hl_get_buf(data_size)) != NULL)
+ {
+ memcpy(p_dcb->p_rx_pkt, p_data, data_size);
+ if (p_dcb->p_scb)
+ {
+ BTIF_TRACE_DEBUG4("app_idx=%d mcl_idx=0x%x mdl_idx=0x%x data_size=%d",
+ app_idx, mcl_idx, mdl_idx, data_size);
+ r = send(p_dcb->p_scb->socket_id[1], p_dcb->p_rx_pkt, data_size, 0);
+
+ if (r == data_size)
+ {
+ BTIF_TRACE_DEBUG1("socket send success data_size=%d", data_size);
+ status = BTA_HL_STATUS_OK;
+ }
+ else
+ {
+ BTIF_TRACE_ERROR2("socket send failed r=%d data_size=%d",r, data_size);
+ }
+
+
+ }
+ btif_hl_free_buf((void **) &p_dcb->p_rx_pkt);
+ }
+ }
+
+ bta_hl_ci_put_rx_data(mdl_handle, status, 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
+**
+*******************************************************************************/
+void bta_hl_co_get_echo_data (UINT8 app_id, tBTA_HL_MCL_HANDLE mcl_handle,
+ UINT16 buf_size, UINT8 *p_buf, UINT16 evt)
+{
+ tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
+
+ BTIF_TRACE_ERROR1("%s not supported",__FUNCTION__);
+ bta_hl_ci_get_echo_data(mcl_handle, status, 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
+**
+*******************************************************************************/
+void bta_hl_co_put_echo_data (UINT8 app_id, tBTA_HL_MCL_HANDLE mcl_handle,
+ UINT16 data_size, UINT8 *p_data, UINT16 evt)
+{
+ tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
+
+ BTIF_TRACE_ERROR1("%s not supported",__FUNCTION__);
+ bta_hl_ci_put_echo_data(mcl_handle, status, evt);
+}
+
diff --git a/btif/co/bta_pan_co.c b/btif/co/bta_pan_co.c
new file mode 100644
index 0000000..e78a5f8
--- /dev/null
+++ b/btif/co/bta_pan_co.c
@@ -0,0 +1,334 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+
+/************************************************************************************
+ *
+ * Filename: bta_pan_co.c
+ *
+ * Description: PAN stack callout api
+ *
+ *
+ ***********************************************************************************/
+#include "bta_api.h"
+#include "bta_pan_api.h"
+#include "bta_pan_ci.h"
+#include "bta_pan_co.h"
+#include "pan_api.h"
+#include "gki.h"
+//#include "btui.h"
+//#include "btui_int.h"
+#include <hardware/bluetooth.h>
+#include <hardware/bt_pan.h>
+#include "btif_pan_internal.h"
+#include "bd.h"
+
+
+#include <cutils/log.h>
+#define info(fmt, ...) ALOGI ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define debug(fmt, ...) ALOGD ("%s: " fmt,__FUNCTION__, ## __VA_ARGS__)
+#define warn(fmt, ...) ALOGW ("## WARNING : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__)
+#define error(fmt, ...) ALOGE ("## ERROR : %s: " fmt "##",__FUNCTION__, ## __VA_ARGS__)
+#define asrt(s) if(!(s)) ALOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_pan_co_init
+**
+** Description
+**
+**
+** Returns Data flow mask.
+**
+*******************************************************************************/
+UINT8 bta_pan_co_init(UINT8 *q_level)
+{
+
+ ALOGD("bta_pan_co_init");
+
+ /* set the q_level to 30 buffers */
+ *q_level = 30;
+
+ //return (BTA_PAN_RX_PULL | BTA_PAN_TX_PULL);
+ return (BTA_PAN_RX_PUSH_BUF | BTA_PAN_RX_PUSH | BTA_PAN_TX_PULL);
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function bta_pan_co_open
+**
+** Description
+**
+**
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+
+void bta_pan_co_open(UINT16 handle, UINT8 app_id, tBTA_PAN_ROLE local_role, tBTA_PAN_ROLE peer_role, BD_ADDR peer_addr)
+{
+ ALOGD("bta_pan_co_open:app_id:%d, local_role:%d, peer_role:%d, handle:%d",
+ app_id, local_role, peer_role, handle);
+ btpan_conn_t* conn = btpan_find_conn_addr(peer_addr);
+ if(conn == NULL)
+ conn = btpan_new_conn(handle, peer_addr, local_role, peer_role);
+ if(conn)
+ {
+ ALOGD("bta_pan_co_open:tap_fd:%d, open_count:%d, conn->handle:%d should = handle:%d, local_role:%d, remote_role:%d",
+ btpan_cb.tap_fd, btpan_cb.open_count, conn->handle, handle, conn->local_role, conn->remote_role);
+ //refresh the role & bt address
+
+ btpan_cb.open_count++;
+ conn->handle = handle;
+ //bdcpy(conn->peer, peer_addr);
+ if(btpan_cb.tap_fd < 0)
+ {
+ btpan_cb.tap_fd = btpan_tap_open();
+ if(btpan_cb.tap_fd >= 0)
+ create_tap_read_thread(btpan_cb.tap_fd);
+ }
+ if(btpan_cb.tap_fd >= 0)
+ {
+ conn->state = PAN_STATE_OPEN;
+ bta_pan_ci_rx_ready(handle);
+ }
+ }
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_co_close
+**
+** Description This function is called by PAN when a connection to a
+** peer is closed.
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_co_close(UINT16 handle, UINT8 app_id)
+{
+ ALOGD("bta_pan_co_close:app_id:%d, handle:%d", app_id, handle);
+ btpan_conn_t* conn = btpan_find_conn_handle(handle);
+ if(conn && conn->state == PAN_STATE_OPEN)
+ {
+ ALOGD("bta_pan_co_close");
+
+ // let bta close event reset this handle as it needs
+ // the handle to find the connection upon CLOSE
+ //conn->handle = -1;
+ conn->state = PAN_STATE_CLOSE;
+ btpan_cb.open_count--;
+
+ if(btpan_cb.open_count == 0)
+ {
+ destroy_tap_read_thread();
+ if(btpan_cb.tap_fd != -1)
+ {
+ btpan_tap_close(btpan_cb.tap_fd);
+ btpan_cb.tap_fd = -1;
+ }
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** 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. 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
+**
+*******************************************************************************/
+void bta_pan_co_tx_path(UINT16 handle, UINT8 app_id)
+{
+ BT_HDR *p_buf;
+ UINT8 i;
+ BD_ADDR src;
+ BD_ADDR dst;
+ UINT16 protocol;
+ BOOLEAN ext;
+ BOOLEAN forward;
+
+ ALOGD("bta_pan_co_tx_path, handle:%d, app_id:%d", handle, app_id);
+
+ btpan_conn_t* conn = btpan_find_conn_handle(handle);
+ if(conn && conn->state != PAN_STATE_OPEN)
+ {
+ ALOGE("bta_pan_co_tx_path: cannot find pan connction or conn is not opened, conn:%p, conn->state:%d", conn, conn->state);
+ return;
+ }
+ do
+ {
+
+ /* read next data buffer from pan */
+ if ((p_buf = bta_pan_ci_readbuf(handle, src, dst, &protocol,
+ &ext, &forward)))
+ {
+ ALOGD("bta_pan_co_tx_path, calling btapp_tap_send, p_buf->len:%d, offset:%d", p_buf->len, p_buf->offset);
+ if(is_empty_eth_addr(conn->eth_addr) && is_valid_bt_eth_addr(src))
+ {
+ ALOGD("pan bt peer addr: %02x:%02x:%02x:%02x:%02x:%02x, update its ethernet addr: %02x:%02x:%02x:%02x:%02x:%02x",
+ conn->peer[0], conn->peer[1], conn->peer[2], conn->peer[3],conn->peer[4], conn->peer[5],
+ src[0], src[1], src[2], src[3],src[4], src[5]);
+ memcpy(conn->eth_addr, src, sizeof(conn->eth_addr));
+
+ }
+ btpan_tap_send(btpan_cb.tap_fd, src, dst, protocol, (char*)(p_buf + 1) + p_buf->offset, p_buf->len, ext, forward);
+ GKI_freebuf(p_buf);
+ }
+
+ } while (p_buf != NULL);
+
+}
+
+/*******************************************************************************
+**
+** Function bta_pan_co_rx_path
+**
+** Description
+**
+**
+**
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_co_rx_path(UINT16 handle, UINT8 app_id)
+{
+
+
+ UINT8 i;
+
+ ALOGD("bta_pan_co_rx_path not used");
+
+
+}
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+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)
+{
+ ALOGD("bta_pan_co_tx_write not used");
+
+}
+
+/*******************************************************************************
+**
+** 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 TRUE if flow enabled
+**
+*******************************************************************************/
+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)
+{
+
+ ALOGD("bta_pan_co_tx_writebuf not used");
+
+
+}
+
+/*******************************************************************************
+**
+** 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
+**
+*******************************************************************************/
+void bta_pan_co_rx_flow(UINT16 handle, UINT8 app_id, BOOLEAN enable)
+{
+
+ ALOGD("bta_pan_co_rx_flow, enabled:%d, not used", enable);
+
+}
+
+
+/*******************************************************************************
+**
+** Function bta_pan_co_filt_ind
+**
+** Description protocol filter indication from peer device
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_co_pfilt_ind(UINT16 handle, BOOLEAN indication, tBTA_PAN_STATUS result,
+ UINT16 len, UINT8 *p_filters)
+{
+ ALOGD("bta_pan_co_pfilt_ind");
+
+}
+/*******************************************************************************
+**
+** Function bta_pan_co_mfilt_ind
+**
+** Description multicast filter indication from peer device
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_pan_co_mfilt_ind(UINT16 handle, BOOLEAN indication, tBTA_PAN_STATUS result,
+ UINT16 len, UINT8 *p_filters)
+{
+
+ ALOGD("bta_pan_co_mfilt_ind");
+}
+
diff --git a/btif/co/bta_sys_co.c b/btif/co/bta_sys_co.c
new file mode 100644
index 0000000..b7768ad
--- /dev/null
+++ b/btif/co/bta_sys_co.c
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#include "bta_sys.h"
+#include "bta_sys_ci.h"
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_co_enable
+**
+** Description This function is called by the stack to power up the HW
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_hw_co_enable( tBTA_SYS_HW_MODULE module )
+{
+ /* platform specific implementation to power-up the HW */
+
+
+ /* if no client/server asynchronous system like linux-based OS, directly call the ci here */
+ bta_sys_hw_ci_enabled( module );
+}
+
+
+/*******************************************************************************
+**
+** Function bta_sys_hw_co_disable
+**
+** Description This function is called by the stack to power down the HW
+**
+** Returns void
+**
+*******************************************************************************/
+void bta_sys_hw_co_disable( tBTA_SYS_HW_MODULE module )
+{
+ /* platform specific implementation to power-down the HW */
+
+
+ /* if no client/server asynchronous system like linux-based OS, directly call the ci here */
+ bta_sys_hw_ci_disabled( module );
+
+}